kafo 0.9.8 → 1.0.0
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 +4 -4
- data/README.md +37 -8
- data/lib/kafo/data_type.rb +100 -0
- data/lib/kafo/data_types/any.rb +8 -0
- data/lib/kafo/data_types/array.rb +62 -0
- data/lib/kafo/data_types/boolean.rb +24 -0
- data/lib/kafo/data_types/enum.rb +25 -0
- data/lib/kafo/data_types/float.rb +40 -0
- data/lib/kafo/data_types/hash.rb +70 -0
- data/lib/kafo/data_types/integer.rb +40 -0
- data/lib/kafo/data_types/not_undef.rb +34 -0
- data/lib/kafo/data_types/numeric.rb +16 -0
- data/lib/kafo/data_types/optional.rb +34 -0
- data/lib/kafo/data_types/pattern.rb +29 -0
- data/lib/kafo/data_types/regexp.rb +14 -0
- data/lib/kafo/data_types/scalar.rb +14 -0
- data/lib/kafo/data_types/string.rb +36 -0
- data/lib/kafo/data_types/struct.rb +100 -0
- data/lib/kafo/data_types/tuple.rb +76 -0
- data/lib/kafo/data_types/type_reference.rb +14 -0
- data/lib/kafo/data_types/undef.rb +12 -0
- data/lib/kafo/data_types/variant.rb +50 -0
- data/lib/kafo/hook_context.rb +2 -0
- data/lib/kafo/kafo_configure.rb +1 -5
- data/lib/kafo/param.rb +19 -33
- data/lib/kafo/param_builder.rb +8 -6
- data/lib/kafo/params/password.rb +0 -8
- data/lib/kafo/version.rb +1 -1
- data/lib/kafo/wizard.rb +1 -0
- metadata +22 -7
- data/lib/kafo/params/array.rb +0 -28
- data/lib/kafo/params/boolean.rb +0 -27
- data/lib/kafo/params/hash.rb +0 -38
- data/lib/kafo/params/integer.rb +0 -19
- data/lib/kafo/params/string.rb +0 -13
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 37920206589ad542c671af010f5b8dd1bb02dff0
         | 
| 4 | 
            +
              data.tar.gz: 3e001186cf0bd9f809a28d92e5223d6345e264e8
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c59eac78e4965f90f98b1bab03275aa2044e724f71e7ed3f90339e7dbc0201812d3cb04bf1ddd0b3b390a309a1c3455620bcd961cadba6fcca01c9b6e581a9f1
         | 
| 7 | 
            +
              data.tar.gz: 797b544447e37f68faf90fe2a54afd033bda2254fa27d18b7c93d1c9ba453644db8b0c145ce9588e5c146507eebdaa60f59ac3321ad379d6f1b64fa3587f05a9
         | 
    
        data/README.md
    CHANGED
    
    | @@ -400,10 +400,10 @@ Example: | |
| 400 400 | 
             
            #
         | 
| 401 401 | 
             
            # $enc::                    Should foreman act as an external node classifier (manage puppet class
         | 
| 402 402 | 
             
            #                           assignments)
         | 
| 403 | 
            -
            # | 
| 403 | 
            +
            #
         | 
| 404 404 | 
             
            class foreman (
         | 
| 405 | 
            -
              $foreman_url | 
| 406 | 
            -
              $enc | 
| 405 | 
            +
              String $foreman_url = $foreman::params::foreman_url,
         | 
| 406 | 
            +
              Boolean $enc        = $foreman::params::enc
         | 
| 407 407 | 
             
            ) {
         | 
| 408 408 | 
             
              class { 'foreman::install': }
         | 
| 409 409 | 
             
            }
         | 
| @@ -445,20 +445,45 @@ the particular parameter belongs. | |
| 445 445 |  | 
| 446 446 | 
             
            ## Argument types
         | 
| 447 447 |  | 
| 448 | 
            -
             | 
| 449 | 
            -
             | 
| 450 | 
            -
             | 
| 448 | 
            +
            When using Puppet 4 or newer, the data type will be read from the parameter
         | 
| 449 | 
            +
            list and defaults to Puppet's [Any](https://docs.puppet.com/puppet/latest/reference/lang_data_abstract.html#any)
         | 
| 450 | 
            +
            data type, which Kafo handles as a basic string with no validation.
         | 
| 451 | 
            +
             | 
| 452 | 
            +
            If more specific data types, such as `Optional[Array[2]]` or similar are
         | 
| 453 | 
            +
            given in the [parameter list](https://docs.puppet.com/puppet/4.5/reference/lang_data_type.html#usage)
         | 
| 454 | 
            +
            then Kafo will parse and validate parameters values according to the
         | 
| 455 | 
            +
            specification.
         | 
| 456 | 
            +
             | 
| 457 | 
            +
            ```puppet
         | 
| 458 | 
            +
            class example (
         | 
| 459 | 
            +
              Boolean $param = false
         | 
| 460 | 
            +
            ) {
         | 
| 461 | 
            +
            ```
         | 
| 462 | 
            +
             | 
| 463 | 
            +
            When using Puppet 3, data types can be specified in the manifest documentation
         | 
| 464 | 
            +
            rather than the parameter list, like this:
         | 
| 451 465 |  | 
| 452 466 | 
             
            ```puppet
         | 
| 453 467 | 
             
            # $param::        Some documentation for param
         | 
| 454 | 
            -
                              type: | 
| 468 | 
            +
                              type:Array[String]
         | 
| 455 469 | 
             
            ```
         | 
| 456 470 |  | 
| 457 | 
            -
             | 
| 471 | 
            +
            For compatibility with older Kafo releases, additional types are supported:
         | 
| 472 | 
            +
            string, boolean, integer, array, password, hash. These are equivalent to their
         | 
| 473 | 
            +
            Puppet 4 namesakes, plus wrapped in `Optional[..]` to permit `undef`.
         | 
| 474 | 
            +
             | 
| 475 | 
            +
            If the data type is given in both the manifest documentation and the parameter
         | 
| 476 | 
            +
            list, then the manifest documentation will be preferred.
         | 
| 458 477 |  | 
| 459 478 | 
             
            Note that all arguments that are nil (have no value in answers.yaml or you
         | 
| 460 479 | 
             
            set them UNDEF (see below)) are translated to ```undef``` in puppet.
         | 
| 461 480 |  | 
| 481 | 
            +
            If your module declares its own types, you can add new corresponding subclasses
         | 
| 482 | 
            +
            of DataType which implement validation and typecasting. This can be added to a
         | 
| 483 | 
            +
            `boot` hook by calling:
         | 
| 484 | 
            +
             | 
| 485 | 
            +
                Kafo::DataType.register_type('YourType', Kafo::DataType::YourType)
         | 
| 486 | 
            +
             | 
| 462 487 | 
             
            ## Password arguments
         | 
| 463 488 |  | 
| 464 489 | 
             
            Kafo supports password arguments. It's adding some level of protection for your
         | 
| @@ -704,6 +729,10 @@ you must follow a few rules however: | |
| 704 729 | 
             
            These functions are re-implemented in Kafo from common stdlib functions, so please
         | 
| 705 730 | 
             
            contribute any missing ones.
         | 
| 706 731 |  | 
| 732 | 
            +
            If class parameters are declared with Puppet 4 data types then Kafo will
         | 
| 733 | 
            +
            validate user inputs against Puppet's type validation rules, which should
         | 
| 734 | 
            +
            replace the use of separate validation functions.
         | 
| 735 | 
            +
             | 
| 707 736 | 
             
            ## Enabling or disabling module
         | 
| 708 737 |  | 
| 709 738 | 
             
            You can enable or disable a module specified in the answers.yaml file. Every module
         | 
| @@ -0,0 +1,100 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              class DataType
         | 
| 3 | 
            +
                def self.new_from_string(str)
         | 
| 4 | 
            +
                  keyword_re = /\A([\w:]+)(?:\[(.*)\])?\z/m.match(str)
         | 
| 5 | 
            +
                  if keyword_re
         | 
| 6 | 
            +
                    if (type = @keywords[keyword_re[1]])
         | 
| 7 | 
            +
                      args = if keyword_re[2]
         | 
| 8 | 
            +
                               hash_re = keyword_re[2].match(/\A\s*{(.*)}\s*\z/m)
         | 
| 9 | 
            +
                               if hash_re
         | 
| 10 | 
            +
                                 [parse_hash(hash_re[1])]
         | 
| 11 | 
            +
                               else
         | 
| 12 | 
            +
                                 split_arguments(keyword_re[2])
         | 
| 13 | 
            +
                               end
         | 
| 14 | 
            +
                             else
         | 
| 15 | 
            +
                               []
         | 
| 16 | 
            +
                             end
         | 
| 17 | 
            +
                      type.new(*args)
         | 
| 18 | 
            +
                    elsif ['Data'].include?(keyword_re[1])
         | 
| 19 | 
            +
                      DataTypes::Any.new
         | 
| 20 | 
            +
                    elsif keyword_re[1] == 'Default'
         | 
| 21 | 
            +
                      DataTypes::Enum.new('default')
         | 
| 22 | 
            +
                    elsif @keywords[keyword_re[1].capitalize]  # pre-Puppet 4 data types
         | 
| 23 | 
            +
                      DataTypes::Optional.new(keyword_re[1].capitalize)
         | 
| 24 | 
            +
                    else
         | 
| 25 | 
            +
                      raise ConfigurationException, "unknown data type #{keyword_re[1]}"
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                  else
         | 
| 28 | 
            +
                    raise ConfigurationException, "data type not recognized #{str}"
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def self.register_type(keyword, type)
         | 
| 33 | 
            +
                  @keywords ||= {}
         | 
| 34 | 
            +
                  raise ArgumentError, "Data type #{keyword} is already registered, cannot be re-registered" if @keywords.has_key?(keyword)
         | 
| 35 | 
            +
                  @keywords[keyword] = type
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def self.types
         | 
| 39 | 
            +
                  @keywords ? @keywords.keys : []
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def self.unregister_type(keyword)
         | 
| 43 | 
            +
                  @keywords.delete(keyword) if @keywords
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def self.split_arguments(input)
         | 
| 47 | 
            +
                  input.scan(%r{\s*["'/]?([\w:]+(?:\[.+\])?|.+?)["'/]?\s*(?:,|$)}m).flatten
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def self.parse_hash(input)
         | 
| 51 | 
            +
                  Hash[input.scan(%r{\s*["'/]?([\w:]+(?:\[[^\]]+\])?|.+?)["'/]?\s*=>\s*["'/]?([\w:]+(?:\[[^\]]+\])?|.+?)["'/]?\s*(?:,|$)}m)]
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                # public interface
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                def condition_value(value)
         | 
| 57 | 
            +
                  value.inspect
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def dump_default(value)
         | 
| 61 | 
            +
                  %{"#{value}"}
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                def multivalued?
         | 
| 65 | 
            +
                  false
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                def to_s
         | 
| 69 | 
            +
                  self.class.name.split('::').last.downcase
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                def typecast(value)
         | 
| 73 | 
            +
                  value == 'UNDEF' ? nil : value
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                def valid?(value, errors = [])
         | 
| 77 | 
            +
                  true
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
            end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            require 'kafo/data_types/any'
         | 
| 83 | 
            +
            require 'kafo/data_types/array'
         | 
| 84 | 
            +
            require 'kafo/data_types/boolean'
         | 
| 85 | 
            +
            require 'kafo/data_types/enum'
         | 
| 86 | 
            +
            require 'kafo/data_types/float'
         | 
| 87 | 
            +
            require 'kafo/data_types/hash'
         | 
| 88 | 
            +
            require 'kafo/data_types/integer'
         | 
| 89 | 
            +
            require 'kafo/data_types/not_undef'
         | 
| 90 | 
            +
            require 'kafo/data_types/numeric'
         | 
| 91 | 
            +
            require 'kafo/data_types/optional'
         | 
| 92 | 
            +
            require 'kafo/data_types/pattern'
         | 
| 93 | 
            +
            require 'kafo/data_types/regexp'
         | 
| 94 | 
            +
            require 'kafo/data_types/scalar'
         | 
| 95 | 
            +
            require 'kafo/data_types/string'
         | 
| 96 | 
            +
            require 'kafo/data_types/struct'
         | 
| 97 | 
            +
            require 'kafo/data_types/tuple'
         | 
| 98 | 
            +
            require 'kafo/data_types/type_reference'
         | 
| 99 | 
            +
            require 'kafo/data_types/undef'
         | 
| 100 | 
            +
            require 'kafo/data_types/variant'
         | 
| @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Array < DataType
         | 
| 4 | 
            +
                  def initialize(inner_type = 'Data', min = :default, max = :default)
         | 
| 5 | 
            +
                    @inner_type = DataType.new_from_string(inner_type)
         | 
| 6 | 
            +
                    @min = (min.to_s == 'default') ? 0 : min.to_i
         | 
| 7 | 
            +
                    @max = (max.to_s == 'default') ? :infinite : max.to_i
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def condition_value(value)
         | 
| 11 | 
            +
                    "[ #{value.map { |v| @inner_type.condition_value(v) }.join(', ')} ]"
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def multivalued?
         | 
| 15 | 
            +
                    true
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def to_s
         | 
| 19 | 
            +
                    type = "array of #{@inner_type}"
         | 
| 20 | 
            +
                    if @min > 0 && @max == :infinite
         | 
| 21 | 
            +
                      "#{type} (at least #{@min} items)"
         | 
| 22 | 
            +
                    elsif @min == 0 && @max != :infinite
         | 
| 23 | 
            +
                      "#{type} (up to #{@max} items)"
         | 
| 24 | 
            +
                    elsif @min > 0 && @max != :infinite
         | 
| 25 | 
            +
                      "#{type} (between #{@min} and #{@max} items)"
         | 
| 26 | 
            +
                    else
         | 
| 27 | 
            +
                      type
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def typecast(value)
         | 
| 32 | 
            +
                    if value.nil?
         | 
| 33 | 
            +
                      nil
         | 
| 34 | 
            +
                    elsif value == ['EMPTY_ARRAY']
         | 
| 35 | 
            +
                      []
         | 
| 36 | 
            +
                    else
         | 
| 37 | 
            +
                      [value].flatten.map { |v| @inner_type.typecast(v) }
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def valid?(input, errors = [])
         | 
| 42 | 
            +
                    unless input.is_a?(::Array)
         | 
| 43 | 
            +
                      errors << "#{input.inspect} is not a valid array"
         | 
| 44 | 
            +
                      return false
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    inner_errors = []
         | 
| 48 | 
            +
                    input.each { |v| @inner_type.valid?(v, inner_errors) }
         | 
| 49 | 
            +
                    unless inner_errors.empty?
         | 
| 50 | 
            +
                      errors << "Elements of the array are invalid: #{inner_errors.join(', ')}"
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    errors << "The array must have at least #{@min} items" if input.size < @min
         | 
| 54 | 
            +
                    errors << "The array must have at maximum #{@max} items" if @max != :infinite && input.size > @max
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    return errors.empty?
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                DataType.register_type('Array', Array)
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
            end
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Boolean < DataType
         | 
| 4 | 
            +
                  def typecast(value)
         | 
| 5 | 
            +
                    case value
         | 
| 6 | 
            +
                      when '0', 'false', 'f', 'n', false
         | 
| 7 | 
            +
                        false
         | 
| 8 | 
            +
                      when '1', 'true', 't', 'y', true
         | 
| 9 | 
            +
                        true
         | 
| 10 | 
            +
                      else
         | 
| 11 | 
            +
                        value
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def valid?(input, errors = [])
         | 
| 16 | 
            +
                    (input.is_a?(::TrueClass) || input.is_a?(::FalseClass)).tap do |valid|
         | 
| 17 | 
            +
                      errors << "#{input.inspect} is not a valid boolean" unless valid
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                DataType.register_type('Boolean', Boolean)
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Enum < DataType
         | 
| 4 | 
            +
                  def initialize(*permitted)
         | 
| 5 | 
            +
                    @permitted = permitted
         | 
| 6 | 
            +
                  end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def to_s
         | 
| 9 | 
            +
                    @permitted.map(&:inspect).join(' or ')
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def valid?(input, errors = [])
         | 
| 13 | 
            +
                    unless input.is_a?(::String)
         | 
| 14 | 
            +
                      errors << "#{input.inspect} is not a valid string"
         | 
| 15 | 
            +
                      return false
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    errors << "#{input} must be one of #{@permitted.join(', ')}" unless @permitted.include?(input)
         | 
| 19 | 
            +
                    return errors.empty?
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                DataType.register_type('Enum', Enum)
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Float < DataType
         | 
| 4 | 
            +
                  def initialize(min = :default, max = :default)
         | 
| 5 | 
            +
                    @min = (min.to_s == 'default') ? :infinite : min.to_i
         | 
| 6 | 
            +
                    @max = (max.to_s == 'default') ? :infinite : max.to_i
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def to_s
         | 
| 10 | 
            +
                    if @min != :infinite && @max == :infinite
         | 
| 11 | 
            +
                      "float (at least #{@min})"
         | 
| 12 | 
            +
                    elsif @min == :infinite && @max != :infinite
         | 
| 13 | 
            +
                      "float (up to #{@max})"
         | 
| 14 | 
            +
                    elsif @min != :infinite && @max != :infinite
         | 
| 15 | 
            +
                      "float (between #{@min} and #{@max})"
         | 
| 16 | 
            +
                    else
         | 
| 17 | 
            +
                      "float"
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def typecast(value)
         | 
| 22 | 
            +
                    value.to_s =~ /\d+/ ? value.to_f : value
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def valid?(input, errors = [])
         | 
| 26 | 
            +
                    unless input.is_a?(::Float)
         | 
| 27 | 
            +
                      errors << "#{input.inspect} is not a valid float"
         | 
| 28 | 
            +
                      return false
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    errors << "#{input} must be at least #{@min}" if @min != :infinite && input < @min
         | 
| 32 | 
            +
                    errors << "#{input} must be up to #{@max}" if @max != :infinite && input > @max
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    return errors.empty?
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                DataType.register_type('Float', Float)
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Hash < DataType
         | 
| 4 | 
            +
                  def initialize(inner_key_type = 'Scalar', inner_value_type = 'Data', min = :default, max = :default)
         | 
| 5 | 
            +
                    @inner_key_type = DataType.new_from_string(inner_key_type)
         | 
| 6 | 
            +
                    @inner_value_type = DataType.new_from_string(inner_value_type)
         | 
| 7 | 
            +
                    @min = (min.to_s == 'default') ? 0 : min.to_i
         | 
| 8 | 
            +
                    @max = (max.to_s == 'default') ? :infinite : max.to_i
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def multivalued?
         | 
| 12 | 
            +
                    true
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def to_s
         | 
| 16 | 
            +
                    type = "hash of #{@inner_key_type}/#{@inner_value_type}"
         | 
| 17 | 
            +
                    if @min > 0 && @max == :infinite
         | 
| 18 | 
            +
                      "#{type} (at least #{@min} items)"
         | 
| 19 | 
            +
                    elsif @min == 0 && @max != :infinite
         | 
| 20 | 
            +
                      "#{type} (up to #{@max} items)"
         | 
| 21 | 
            +
                    elsif @min > 0 && @max != :infinite
         | 
| 22 | 
            +
                      "#{type} (between #{@min} and #{@max} items)"
         | 
| 23 | 
            +
                    else
         | 
| 24 | 
            +
                      type
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def typecast(value)
         | 
| 29 | 
            +
                    if value.nil?
         | 
| 30 | 
            +
                      nil
         | 
| 31 | 
            +
                    elsif value.is_a?(::Hash)
         | 
| 32 | 
            +
                      value
         | 
| 33 | 
            +
                    elsif value == ['EMPTY_HASH']
         | 
| 34 | 
            +
                      {}
         | 
| 35 | 
            +
                    else
         | 
| 36 | 
            +
                      ::Hash[[value].flatten.map do |kv|
         | 
| 37 | 
            +
                        k, v = kv.split(':', 2)
         | 
| 38 | 
            +
                        [@inner_key_type.typecast(k), @inner_value_type.typecast(v)]
         | 
| 39 | 
            +
                      end]
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def valid?(input, errors = [])
         | 
| 44 | 
            +
                    unless input.is_a?(::Hash)
         | 
| 45 | 
            +
                      errors << "#{input.inspect} is not a valid hash"
         | 
| 46 | 
            +
                      return false
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    inner_key_errors = []
         | 
| 50 | 
            +
                    input.keys.each { |v| @inner_key_type.valid?(v, inner_key_errors) }
         | 
| 51 | 
            +
                    unless inner_key_errors.empty?
         | 
| 52 | 
            +
                      errors << "Hash key elements are invalid: #{inner_key_errors.join(', ')}"
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    inner_value_errors = []
         | 
| 56 | 
            +
                    input.values.each { |v| @inner_value_type.valid?(v, inner_value_errors) }
         | 
| 57 | 
            +
                    unless inner_value_errors.empty?
         | 
| 58 | 
            +
                      errors << "Hash value elements are invalid: #{inner_value_errors.join(', ')}"
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    errors << "The hash must have at least #{@min} items" if input.size < @min
         | 
| 62 | 
            +
                    errors << "The hash must have at maximum #{@max} items" if @max != :infinite && input.size > @max
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    return errors.empty?
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                DataType.register_type('Hash', Hash)
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Integer < DataType
         | 
| 4 | 
            +
                  def initialize(min = :default, max = :default)
         | 
| 5 | 
            +
                    @min = (min.to_s == 'default') ? :infinite : min.to_i
         | 
| 6 | 
            +
                    @max = (max.to_s == 'default') ? :infinite : max.to_i
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def to_s
         | 
| 10 | 
            +
                    if @min != :infinite && @max == :infinite
         | 
| 11 | 
            +
                      "integer (at least #{@min})"
         | 
| 12 | 
            +
                    elsif @min == :infinite && @max != :infinite
         | 
| 13 | 
            +
                      "integer (up to #{@max})"
         | 
| 14 | 
            +
                    elsif @min != :infinite && @max != :infinite
         | 
| 15 | 
            +
                      "integer (between #{@min} and #{@max})"
         | 
| 16 | 
            +
                    else
         | 
| 17 | 
            +
                      "integer"
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def typecast(value)
         | 
| 22 | 
            +
                    value =~ /\d+/ ? value.to_i : value
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def valid?(input, errors = [])
         | 
| 26 | 
            +
                    unless input.is_a?(::Integer)
         | 
| 27 | 
            +
                      errors << "#{input.inspect} is not a valid integer"
         | 
| 28 | 
            +
                      return false
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    errors << "#{input} must be at least #{@min}" if @min != :infinite && input < @min
         | 
| 32 | 
            +
                    errors << "#{input} must be up to #{@max}" if @max != :infinite && input > @max
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    return errors.empty?
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                DataType.register_type('Integer', Integer)
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class NotUndef < DataType
         | 
| 4 | 
            +
                  extend Forwardable
         | 
| 5 | 
            +
                  def_delegators :@inner_type, :condition_value, :dump_default, :multivalued?, :typecast
         | 
| 6 | 
            +
                  attr_reader :inner_type, :inner_value
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def initialize(inner_type_or_value)
         | 
| 9 | 
            +
                    begin
         | 
| 10 | 
            +
                      @inner_type = DataType.new_from_string(inner_type_or_value)
         | 
| 11 | 
            +
                    rescue ConfigurationException
         | 
| 12 | 
            +
                      @inner_value = inner_type_or_value
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def to_s
         | 
| 17 | 
            +
                    if @inner_type
         | 
| 18 | 
            +
                      "#{@inner_type} but not undef"
         | 
| 19 | 
            +
                    else
         | 
| 20 | 
            +
                      "#{@inner_value.inspect} but not undef"
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def valid?(input, errors = [])
         | 
| 25 | 
            +
                    return false if input.nil?
         | 
| 26 | 
            +
                    return true if @inner_type && @inner_type.valid?(input, errors)
         | 
| 27 | 
            +
                    return true if @inner_value && @inner_value == input
         | 
| 28 | 
            +
                    return false
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                DataType.register_type('NotUndef', NotUndef)
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Numeric < DataType
         | 
| 4 | 
            +
                  def typecast(value)
         | 
| 5 | 
            +
                    value =~ /\d+/ ? value.to_f : value
         | 
| 6 | 
            +
                  end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def valid?(input, errors = [])
         | 
| 9 | 
            +
                    errors << "#{input.inspect} is not a valid number" unless input.is_a?(::Integer) || input.is_a?(::Float)
         | 
| 10 | 
            +
                    return errors.empty?
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                DataType.register_type('Numeric', Numeric)
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Optional < DataType
         | 
| 4 | 
            +
                  extend Forwardable
         | 
| 5 | 
            +
                  def_delegators :@inner_type, :condition_value, :dump_default, :multivalued?, :typecast
         | 
| 6 | 
            +
                  attr_reader :inner_type, :inner_value
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def initialize(inner_type_or_value)
         | 
| 9 | 
            +
                    begin
         | 
| 10 | 
            +
                      @inner_type = DataType.new_from_string(inner_type_or_value)
         | 
| 11 | 
            +
                    rescue ConfigurationException
         | 
| 12 | 
            +
                      @inner_value = inner_type_or_value
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def to_s
         | 
| 17 | 
            +
                    if @inner_type
         | 
| 18 | 
            +
                      "#{@inner_type} or undef"
         | 
| 19 | 
            +
                    else
         | 
| 20 | 
            +
                      "#{@inner_value.inspect} or undef"
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def valid?(input, errors = [])
         | 
| 25 | 
            +
                    return true if input.nil?
         | 
| 26 | 
            +
                    return true if @inner_type && @inner_type.valid?(input, errors)
         | 
| 27 | 
            +
                    return true if @inner_value && @inner_value == input
         | 
| 28 | 
            +
                    return false
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                DataType.register_type('Optional', Optional)
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Pattern < DataType
         | 
| 4 | 
            +
                  def initialize(*regexes)
         | 
| 5 | 
            +
                    @regex_strings = regexes
         | 
| 6 | 
            +
                    @regexes = regexes.map { |r| ::Regexp.new(r) }
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def to_s
         | 
| 10 | 
            +
                    "regexes matching #{@regex_strings.map { |r| "/#{r}/" }.join(' or ')}"
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def valid?(input, errors = [])
         | 
| 14 | 
            +
                    unless input.is_a?(::String)
         | 
| 15 | 
            +
                      errors << "#{input.inspect} is not a valid string"
         | 
| 16 | 
            +
                      return false
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    unless @regexes.any? { |r| r.match(input) }
         | 
| 20 | 
            +
                      errors << "#{input} must match one of #{@regexes.join(', ')}"
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    return errors.empty?
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                DataType.register_type('Pattern', Pattern)
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Regexp < DataType
         | 
| 4 | 
            +
                  extend Forwardable
         | 
| 5 | 
            +
                  def_delegators :@inner_type, :condition_value, :dump_default, :multivalued?, :typecast, :valid?
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize
         | 
| 8 | 
            +
                    @inner_type = DataTypes::String.new
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                DataType.register_type('Regexp', Regexp)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Scalar < DataType
         | 
| 4 | 
            +
                  extend Forwardable
         | 
| 5 | 
            +
                  def_delegators :@inner_type, :condition_value, :dump_default, :multivalued?, :typecast, :valid?
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize
         | 
| 8 | 
            +
                    @inner_type = DataTypes::Variant.new('Integer', 'Float', 'String', 'Boolean', 'Regexp')
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                DataType.register_type('Scalar', Scalar)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class String < DataType
         | 
| 4 | 
            +
                  def initialize(min = :default, max = :default)
         | 
| 5 | 
            +
                    @min = (min.to_s == 'default') ? 0 : min.to_i
         | 
| 6 | 
            +
                    @max = (max.to_s == 'default') ? :infinite : max.to_i
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def to_s
         | 
| 10 | 
            +
                    if @min > 0 && @max == :infinite
         | 
| 11 | 
            +
                      "string (at least #{@min} characters)"
         | 
| 12 | 
            +
                    elsif @min == 0 && @max != :infinite
         | 
| 13 | 
            +
                      "string (up to #{@max} characters)"
         | 
| 14 | 
            +
                    elsif @min > 0 && @max != :infinite
         | 
| 15 | 
            +
                      "string (between #{@min} and #{@max} characters)"
         | 
| 16 | 
            +
                    else
         | 
| 17 | 
            +
                      "string"
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def valid?(input, errors = [])
         | 
| 22 | 
            +
                    unless input.is_a?(::String)
         | 
| 23 | 
            +
                      errors << "#{input.inspect} is not a valid string"
         | 
| 24 | 
            +
                      return false
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    errors << "#{input} must be at least #{@min}" if input.size < @min
         | 
| 28 | 
            +
                    errors << "#{input} must be up to #{@max}" if @max != :infinite && input.size > @max
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    return errors.empty?
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                DataType.register_type('String', String)
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,100 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Struct < DataType
         | 
| 4 | 
            +
                  def initialize(spec)
         | 
| 5 | 
            +
                    @spec = ::Hash[spec.map do |k,v|
         | 
| 6 | 
            +
                      begin
         | 
| 7 | 
            +
                        k = DataType.new_from_string(k)
         | 
| 8 | 
            +
                      rescue ConfigurationException; end
         | 
| 9 | 
            +
                      begin
         | 
| 10 | 
            +
                        v = DataType.new_from_string(v)
         | 
| 11 | 
            +
                      rescue ConfigurationException; end
         | 
| 12 | 
            +
                      [k, v]
         | 
| 13 | 
            +
                    end]
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def multivalued?
         | 
| 17 | 
            +
                    true
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def to_s
         | 
| 21 | 
            +
                    "struct containing " + @spec.keys.map do |k|
         | 
| 22 | 
            +
                      if k.is_a?(Optional)
         | 
| 23 | 
            +
                        [k.inner_value, %{"#{k.inner_value}" (optional #{@spec[k]})}]
         | 
| 24 | 
            +
                      elsif k.is_a?(NotUndef)
         | 
| 25 | 
            +
                        [k.inner_value, %{"#{k.inner_value}" (required #{@spec[k]})}]
         | 
| 26 | 
            +
                      else
         | 
| 27 | 
            +
                        [k, %{"#{k}" (#{@spec[k]})}]
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
                    end.sort_by(&:first).map(&:last).join(', ')
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def typecast(value)
         | 
| 33 | 
            +
                    if value.nil?
         | 
| 34 | 
            +
                      nil
         | 
| 35 | 
            +
                    elsif value.is_a?(::Hash)
         | 
| 36 | 
            +
                      value
         | 
| 37 | 
            +
                    elsif value == ['EMPTY_HASH']
         | 
| 38 | 
            +
                      {}
         | 
| 39 | 
            +
                    else
         | 
| 40 | 
            +
                      ::Hash[[value].flatten.map do |kv|
         | 
| 41 | 
            +
                        k, v = kv.split(':', 2)
         | 
| 42 | 
            +
                        if (value_type = spec_value(k))
         | 
| 43 | 
            +
                          [k, value_type.typecast(v)]
         | 
| 44 | 
            +
                        else
         | 
| 45 | 
            +
                          [k, v]
         | 
| 46 | 
            +
                        end
         | 
| 47 | 
            +
                      end]
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  def valid?(input, errors = [])
         | 
| 52 | 
            +
                    unless input.is_a?(::Hash)
         | 
| 53 | 
            +
                      errors << "#{input.inspect} is not a valid struct"
         | 
| 54 | 
            +
                      return false
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    required_keys = @spec.keys.select { |k| k.is_a?(NotUndef) }.map { |k| k.inner_value }
         | 
| 58 | 
            +
                    missing_keys = required_keys - input.keys
         | 
| 59 | 
            +
                    errors << "Struct elements are missing: #{missing_keys.join(', ')}" unless missing_keys.empty?
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    known_keys = @spec.keys.map { |k| spec_key_name(k) }
         | 
| 62 | 
            +
                    extra_keys = input.keys - known_keys
         | 
| 63 | 
            +
                    errors << "Struct elements are not permitted: #{extra_keys.join(', ')}" unless extra_keys.empty?
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    value_errors = []
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    # Only check values for optional keys if present
         | 
| 68 | 
            +
                    optional_keys = @spec.keys.select { |k| k.is_a?(Optional) }.map { |k| k.inner_value }
         | 
| 69 | 
            +
                    (optional_keys & input.keys).each { |k| spec_value(k).valid?(input[k], value_errors) }
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                    # For non-optional and non-required keys, assume nil/undef values if absent
         | 
| 72 | 
            +
                    regular_keys = @spec.keys.select { |k| !k.is_a?(Optional) }.map { |k| spec_key_name(k) }
         | 
| 73 | 
            +
                    regular_keys.each { |k| spec_value(k).valid?(input[k], value_errors) }
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    errors << "Struct values are invalid: #{value_errors.join(', ')}" unless value_errors.empty?
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    return errors.empty?
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  private
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                  def spec_value(key)
         | 
| 83 | 
            +
                    spec_entry = @spec.find do |k,v|
         | 
| 84 | 
            +
                      spec_key_name(k) == key
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
                    spec_entry ? spec_entry.last : nil
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  def spec_key_name(key)
         | 
| 90 | 
            +
                    if key.is_a?(Optional) || key.is_a?(NotUndef)
         | 
| 91 | 
            +
                      key.inner_value
         | 
| 92 | 
            +
                    else
         | 
| 93 | 
            +
                      key
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                DataType.register_type('Struct', Struct)
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
            end
         | 
| @@ -0,0 +1,76 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Tuple < DataType
         | 
| 4 | 
            +
                  def initialize(*args)
         | 
| 5 | 
            +
                    if args.last.to_s =~ /\d+/ || args.last.to_s == 'default'
         | 
| 6 | 
            +
                      max = args.pop
         | 
| 7 | 
            +
                      min = args.pop
         | 
| 8 | 
            +
                    else
         | 
| 9 | 
            +
                      max = :default
         | 
| 10 | 
            +
                      min = :default
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
                    @max = (max.to_s == 'default') ? :infinite : max.to_i
         | 
| 13 | 
            +
                    @min = (min.to_s == 'default') ? 0 : min.to_i
         | 
| 14 | 
            +
                    @inner_types = args.map { |type| DataType.new_from_string(type) }
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def condition_value(value)
         | 
| 18 | 
            +
                    "[ #{value.each_with_index.map { |v,i| inner_types(value)[i].condition_value(v) }.join(', ')} ]"
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def multivalued?
         | 
| 22 | 
            +
                    true
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def to_s
         | 
| 26 | 
            +
                    type = "tuple of #{@inner_types.join(', ')}"
         | 
| 27 | 
            +
                    if @min > 0 && @max == :infinite
         | 
| 28 | 
            +
                      "#{type} (at least #{@min} items)"
         | 
| 29 | 
            +
                    elsif @min == 0 && @max != :infinite
         | 
| 30 | 
            +
                      "#{type} (up to #{@max} items)"
         | 
| 31 | 
            +
                    elsif @min > 0 && @max != :infinite
         | 
| 32 | 
            +
                      "#{type} (between #{@min} and #{@max} items)"
         | 
| 33 | 
            +
                    else
         | 
| 34 | 
            +
                      type
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def typecast(value)
         | 
| 39 | 
            +
                    if value.nil?
         | 
| 40 | 
            +
                      nil
         | 
| 41 | 
            +
                    elsif value == ['EMPTY_ARRAY']
         | 
| 42 | 
            +
                      []
         | 
| 43 | 
            +
                    else
         | 
| 44 | 
            +
                      values = [value].flatten
         | 
| 45 | 
            +
                      values.each_with_index.map { |v,i| inner_types(values)[i].typecast(v) }
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def valid?(input, errors = [])
         | 
| 50 | 
            +
                    unless input.is_a?(::Array)
         | 
| 51 | 
            +
                      errors << "#{input.inspect} is not a valid tuple"
         | 
| 52 | 
            +
                      return false
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    inner_errors = []
         | 
| 56 | 
            +
                    input.each_with_index { |v,i| inner_types(input)[i].valid?(v, inner_errors) }
         | 
| 57 | 
            +
                    unless inner_errors.empty?
         | 
| 58 | 
            +
                      errors << "Elements of the tuple are invalid: #{inner_errors.join(', ')}"
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    errors << "The tuple must have at least #{@min} items" if input.size < @min
         | 
| 62 | 
            +
                    errors << "The tuple must have at maximum #{@max} items" if @max != :infinite && input.size > @max
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    return errors.empty?
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  private
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  def inner_types(value)
         | 
| 70 | 
            +
                    @inner_types + ([@inner_types.last] * (value.size - @inner_types.size))
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                DataType.register_type('Tuple', Tuple)
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class TypeReference < DataType
         | 
| 4 | 
            +
                  extend Forwardable
         | 
| 5 | 
            +
                  def_delegators :@inner_type, :condition_value, :dump_default, :multivalued?, :to_s, :typecast, :valid?
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize(inner_type)
         | 
| 8 | 
            +
                    @inner_type = DataType.new_from_string(inner_type)
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                DataType.register_type('TypeReference', TypeReference)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            module Kafo
         | 
| 2 | 
            +
              module DataTypes
         | 
| 3 | 
            +
                class Variant < DataType
         | 
| 4 | 
            +
                  def initialize(*inner_types)
         | 
| 5 | 
            +
                    @inner_types = inner_types.map { |t| DataType.new_from_string(t) }
         | 
| 6 | 
            +
                  end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def condition_value(value)
         | 
| 9 | 
            +
                    type = find_type(value)
         | 
| 10 | 
            +
                    type ? type.condition_value(value) : super(value)
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def dump_default(value)
         | 
| 14 | 
            +
                    type = find_type(value)
         | 
| 15 | 
            +
                    type ? type.dump_default(value) : super(value)
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def multivalued?
         | 
| 19 | 
            +
                    @inner_types.any? { |t| t.multivalued? }
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def to_s
         | 
| 23 | 
            +
                    @inner_types.join(' or ')
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def typecast(value)
         | 
| 27 | 
            +
                    type = find_type(value)
         | 
| 28 | 
            +
                    type ? type.typecast(value) : value
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def valid?(value, errors = [])
         | 
| 32 | 
            +
                    type = find_type(value)
         | 
| 33 | 
            +
                    if type
         | 
| 34 | 
            +
                      type.valid?(value, errors)
         | 
| 35 | 
            +
                    else
         | 
| 36 | 
            +
                      errors << "#{value} is not one of #{to_s}"
         | 
| 37 | 
            +
                      false
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  private
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def find_type(value)
         | 
| 44 | 
            +
                    @inner_types.find { |t| t.valid?(t.typecast(value)) }
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                DataType.register_type('Variant', Variant)
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
    
        data/lib/kafo/hook_context.rb
    CHANGED
    
    
    
        data/lib/kafo/kafo_configure.rb
    CHANGED
    
    | @@ -197,10 +197,6 @@ module Kafo | |
| 197 197 | 
             
                  self.class.exit(:unknown_module)
         | 
| 198 198 | 
             
                end
         | 
| 199 199 |  | 
| 200 | 
            -
                def enabled_params
         | 
| 201 | 
            -
                  params.select { |p| p.module.enabled? }
         | 
| 202 | 
            -
                end
         | 
| 203 | 
            -
             | 
| 204 200 | 
             
                def reset_params_cache
         | 
| 205 201 | 
             
                  @params = nil
         | 
| 206 202 | 
             
                  params
         | 
| @@ -395,7 +391,7 @@ module Kafo | |
| 395 391 |  | 
| 396 392 | 
             
                def validate_all(logging = true)
         | 
| 397 393 | 
             
                  logger.info 'Running validation checks'
         | 
| 398 | 
            -
                  results =  | 
| 394 | 
            +
                  results = params.map do |param|
         | 
| 399 395 | 
             
                    result = param.valid?
         | 
| 400 396 | 
             
                    errors = param.validation_errors.join(', ')
         | 
| 401 397 | 
             
                    progress_log(:error, "Parameter #{with_prefix(param)} invalid: #{errors}") if logging && !result
         | 
    
        data/lib/kafo/param.rb
    CHANGED
    
    | @@ -1,15 +1,17 @@ | |
| 1 1 | 
             
            # encoding: UTF-8
         | 
| 2 2 | 
             
            require 'kafo/condition'
         | 
| 3 | 
            +
            require 'kafo/validator'
         | 
| 3 4 |  | 
| 4 5 | 
             
            module Kafo
         | 
| 5 6 | 
             
              class Param
         | 
| 6 | 
            -
                attr_reader :name, :module
         | 
| 7 | 
            +
                attr_reader :name, :module, :type
         | 
| 7 8 | 
             
                attr_accessor :default, :doc, :value_set, :condition
         | 
| 8 9 | 
             
                attr_writer :groups
         | 
| 9 10 |  | 
| 10 | 
            -
                def initialize(builder, name)
         | 
| 11 | 
            +
                def initialize(builder, name, type)
         | 
| 11 12 | 
             
                  @name   = name
         | 
| 12 13 | 
             
                  @module = builder
         | 
| 14 | 
            +
                  @type   = DataType.new_from_string(type)
         | 
| 13 15 | 
             
                end
         | 
| 14 16 |  | 
| 15 17 | 
             
                def groups
         | 
| @@ -18,12 +20,13 @@ module Kafo | |
| 18 20 |  | 
| 19 21 | 
             
                # we use @value_set flag because even nil can be valid value
         | 
| 20 22 | 
             
                def value
         | 
| 21 | 
            -
                  @value_set ? @value : default
         | 
| 23 | 
            +
                  @value_set ? @type.typecast(@value) : default
         | 
| 22 24 | 
             
                end
         | 
| 23 25 |  | 
| 24 26 | 
             
                def value=(value)
         | 
| 25 27 | 
             
                  @value_set = true
         | 
| 26 | 
            -
                   | 
| 28 | 
            +
                  value      = value.to_s if value.is_a?(::HighLine::String)  # don't persist highline extensions
         | 
| 29 | 
            +
                  @value     = value
         | 
| 27 30 | 
             
                end
         | 
| 28 31 |  | 
| 29 32 | 
             
                def unset_value
         | 
| @@ -32,7 +35,7 @@ module Kafo | |
| 32 35 | 
             
                end
         | 
| 33 36 |  | 
| 34 37 | 
             
                def dump_default
         | 
| 35 | 
            -
                  default
         | 
| 38 | 
            +
                  @type.dump_default(default)
         | 
| 36 39 | 
             
                end
         | 
| 37 40 |  | 
| 38 41 | 
             
                def module_name
         | 
| @@ -40,7 +43,7 @@ module Kafo | |
| 40 43 | 
             
                end
         | 
| 41 44 |  | 
| 42 45 | 
             
                def to_s
         | 
| 43 | 
            -
                  "#<#{self.class}:#{self.object_id} @name=#{name.inspect} @default=#{default.inspect} @value=#{value.inspect}>"
         | 
| 46 | 
            +
                  "#<#{self.class}:#{self.object_id} @name=#{name.inspect} @default=#{default.inspect} @value=#{value.inspect} @type=#{@type}>"
         | 
| 44 47 | 
             
                end
         | 
| 45 48 |  | 
| 46 49 | 
             
                def set_default(defaults)
         | 
| @@ -86,22 +89,23 @@ module Kafo | |
| 86 89 | 
             
                    {:name => v.name, :arguments => interpret_validation_args(args)}
         | 
| 87 90 | 
             
                  end
         | 
| 88 91 |  | 
| 92 | 
            +
                  # run old style validation functions
         | 
| 89 93 | 
             
                  @validator = Validator.new
         | 
| 90 94 | 
             
                  validations.each { |v| @validator.send(v[:name], v[:arguments]) }
         | 
| 91 | 
            -
                  @validator.errors. | 
| 95 | 
            +
                  @validation_errors = @validator.errors.dup
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  # run data type based validations, append errors
         | 
| 98 | 
            +
                  @type.valid?(value, @validation_errors)
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  @validation_errors.empty?
         | 
| 92 101 | 
             
                end
         | 
| 93 102 |  | 
| 94 103 | 
             
                def validation_errors
         | 
| 95 | 
            -
                   | 
| 96 | 
            -
                    @validator.errors
         | 
| 97 | 
            -
                  else
         | 
| 98 | 
            -
                    []
         | 
| 99 | 
            -
                  end
         | 
| 104 | 
            +
                  @validation_errors || []
         | 
| 100 105 | 
             
                end
         | 
| 101 106 |  | 
| 102 | 
            -
                # To be overwritten in children
         | 
| 103 107 | 
             
                def multivalued?
         | 
| 104 | 
            -
                   | 
| 108 | 
            +
                  @type.multivalued?
         | 
| 105 109 | 
             
                end
         | 
| 106 110 |  | 
| 107 111 | 
             
                def <=> o
         | 
| @@ -117,7 +121,7 @@ module Kafo | |
| 117 121 | 
             
                end
         | 
| 118 122 |  | 
| 119 123 | 
             
                def condition_value
         | 
| 120 | 
            -
                  value | 
| 124 | 
            +
                  @type.condition_value(value)
         | 
| 121 125 | 
             
                end
         | 
| 122 126 |  | 
| 123 127 | 
             
                private
         | 
| @@ -139,25 +143,7 @@ module Kafo | |
| 139 143 | 
             
                    arg == :undef ? nil : arg
         | 
| 140 144 | 
             
                  end
         | 
| 141 145 | 
             
                end
         | 
| 142 | 
            -
             | 
| 143 | 
            -
                def normalize_value(value)
         | 
| 144 | 
            -
                  case value
         | 
| 145 | 
            -
                    when ::HighLine::String  # don't persist highline extensions
         | 
| 146 | 
            -
                      value.to_s
         | 
| 147 | 
            -
                    when Array
         | 
| 148 | 
            -
                      value.map { |v| normalize_value(v) }
         | 
| 149 | 
            -
                    when Hash
         | 
| 150 | 
            -
                      Hash[value.map { |k,v| [normalize_value(k), normalize_value(v)] }]
         | 
| 151 | 
            -
                    else
         | 
| 152 | 
            -
                      value
         | 
| 153 | 
            -
                  end
         | 
| 154 | 
            -
                end
         | 
| 155 146 | 
             
              end
         | 
| 156 147 | 
             
            end
         | 
| 157 148 |  | 
| 158 | 
            -
            require 'kafo/params/boolean'
         | 
| 159 | 
            -
            require 'kafo/params/string'
         | 
| 160 149 | 
             
            require 'kafo/params/password'
         | 
| 161 | 
            -
            require 'kafo/params/array'
         | 
| 162 | 
            -
            require 'kafo/params/hash'
         | 
| 163 | 
            -
            require 'kafo/params/integer'
         | 
    
        data/lib/kafo/param_builder.rb
    CHANGED
    
    | @@ -52,7 +52,14 @@ module Kafo | |
| 52 52 | 
             
                end
         | 
| 53 53 |  | 
| 54 54 | 
             
                def build(name, data)
         | 
| 55 | 
            -
                   | 
| 55 | 
            +
                  data_type = data[:types][name] || 'Data'
         | 
| 56 | 
            +
                  if data_type == 'password'
         | 
| 57 | 
            +
                    type = Params::Password
         | 
| 58 | 
            +
                    data_type = 'String'
         | 
| 59 | 
            +
                  else
         | 
| 60 | 
            +
                    type = Param
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                  param           = type.new(@module, name, data_type)
         | 
| 56 63 | 
             
                  param.default   = data[:values][name]
         | 
| 57 64 | 
             
                  param.doc       = data[:docs][name]
         | 
| 58 65 | 
             
                  param.groups    = data[:groups][name]
         | 
| @@ -77,10 +84,5 @@ module Kafo | |
| 77 84 | 
             
                  end
         | 
| 78 85 | 
             
                  param_group
         | 
| 79 86 | 
             
                end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                def get_type(type)
         | 
| 82 | 
            -
                  type = (type || 'string').capitalize
         | 
| 83 | 
            -
                  Params.const_defined?(type) ? Params.const_get(type) : raise(TypeError, "undefined parameter type '#{type}'")
         | 
| 84 | 
            -
                end
         | 
| 85 87 | 
             
              end
         | 
| 86 88 | 
             
            end
         | 
    
        data/lib/kafo/params/password.rb
    CHANGED
    
    
    
        data/lib/kafo/version.rb
    CHANGED
    
    
    
        data/lib/kafo/wizard.rb
    CHANGED
    
    | @@ -124,6 +124,7 @@ END | |
| 124 124 | 
             
                def configure(param)
         | 
| 125 125 | 
             
                  say "\n" + HighLine.color("Parameter #{param.name} (of module #{param.module.name})", :headline)
         | 
| 126 126 | 
             
                  say HighLine.color(param.doc.join("\n").gsub('"', '\"'), :important)
         | 
| 127 | 
            +
                  say HighLine.color("Data type: #{param.type}", :important)
         | 
| 127 128 | 
             
                  value       = param.multivalued? ? configure_multi(param) : configure_single(param)
         | 
| 128 129 | 
             
                  value_was   = param.value
         | 
| 129 130 | 
             
                  param.value = value unless value.empty?
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: kafo
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 1.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Marek Hulan
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016- | 
| 11 | 
            +
            date: 2016-09-13 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -220,6 +220,26 @@ files: | |
| 220 220 | 
             
            - lib/kafo/color_scheme.rb
         | 
| 221 221 | 
             
            - lib/kafo/condition.rb
         | 
| 222 222 | 
             
            - lib/kafo/configuration.rb
         | 
| 223 | 
            +
            - lib/kafo/data_type.rb
         | 
| 224 | 
            +
            - lib/kafo/data_types/any.rb
         | 
| 225 | 
            +
            - lib/kafo/data_types/array.rb
         | 
| 226 | 
            +
            - lib/kafo/data_types/boolean.rb
         | 
| 227 | 
            +
            - lib/kafo/data_types/enum.rb
         | 
| 228 | 
            +
            - lib/kafo/data_types/float.rb
         | 
| 229 | 
            +
            - lib/kafo/data_types/hash.rb
         | 
| 230 | 
            +
            - lib/kafo/data_types/integer.rb
         | 
| 231 | 
            +
            - lib/kafo/data_types/not_undef.rb
         | 
| 232 | 
            +
            - lib/kafo/data_types/numeric.rb
         | 
| 233 | 
            +
            - lib/kafo/data_types/optional.rb
         | 
| 234 | 
            +
            - lib/kafo/data_types/pattern.rb
         | 
| 235 | 
            +
            - lib/kafo/data_types/regexp.rb
         | 
| 236 | 
            +
            - lib/kafo/data_types/scalar.rb
         | 
| 237 | 
            +
            - lib/kafo/data_types/string.rb
         | 
| 238 | 
            +
            - lib/kafo/data_types/struct.rb
         | 
| 239 | 
            +
            - lib/kafo/data_types/tuple.rb
         | 
| 240 | 
            +
            - lib/kafo/data_types/type_reference.rb
         | 
| 241 | 
            +
            - lib/kafo/data_types/undef.rb
         | 
| 242 | 
            +
            - lib/kafo/data_types/variant.rb
         | 
| 223 243 | 
             
            - lib/kafo/exceptions.rb
         | 
| 224 244 | 
             
            - lib/kafo/exit_handler.rb
         | 
| 225 245 | 
             
            - lib/kafo/help_builder.rb
         | 
| @@ -236,12 +256,7 @@ files: | |
| 236 256 | 
             
            - lib/kafo/param.rb
         | 
| 237 257 | 
             
            - lib/kafo/param_builder.rb
         | 
| 238 258 | 
             
            - lib/kafo/param_group.rb
         | 
| 239 | 
            -
            - lib/kafo/params/array.rb
         | 
| 240 | 
            -
            - lib/kafo/params/boolean.rb
         | 
| 241 | 
            -
            - lib/kafo/params/hash.rb
         | 
| 242 | 
            -
            - lib/kafo/params/integer.rb
         | 
| 243 259 | 
             
            - lib/kafo/params/password.rb
         | 
| 244 | 
            -
            - lib/kafo/params/string.rb
         | 
| 245 260 | 
             
            - lib/kafo/parser_cache_reader.rb
         | 
| 246 261 | 
             
            - lib/kafo/parser_cache_writer.rb
         | 
| 247 262 | 
             
            - lib/kafo/password_manager.rb
         | 
    
        data/lib/kafo/params/array.rb
    DELETED
    
    | @@ -1,28 +0,0 @@ | |
| 1 | 
            -
            module Kafo
         | 
| 2 | 
            -
              module Params
         | 
| 3 | 
            -
                class Array < Param
         | 
| 4 | 
            -
                  def value=(value)
         | 
| 5 | 
            -
                    super
         | 
| 6 | 
            -
                    if @value == ['EMPTY_ARRAY']
         | 
| 7 | 
            -
                      @value = []
         | 
| 8 | 
            -
                    else
         | 
| 9 | 
            -
                      @value = typecast(@value)
         | 
| 10 | 
            -
                    end
         | 
| 11 | 
            -
                  end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                  def multivalued?
         | 
| 14 | 
            -
                    true
         | 
| 15 | 
            -
                  end
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                  def condition_value
         | 
| 18 | 
            -
                    "[ #{value.map(&:inspect).join(', ')} ]"
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                  private
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                  def typecast(value)
         | 
| 24 | 
            -
                    value.nil? ? nil : [value].flatten
         | 
| 25 | 
            -
                  end
         | 
| 26 | 
            -
                end
         | 
| 27 | 
            -
              end
         | 
| 28 | 
            -
            end
         | 
    
        data/lib/kafo/params/boolean.rb
    DELETED
    
    | @@ -1,27 +0,0 @@ | |
| 1 | 
            -
            module Kafo
         | 
| 2 | 
            -
              module Params
         | 
| 3 | 
            -
                class Boolean < Param
         | 
| 4 | 
            -
                  def value=(value)
         | 
| 5 | 
            -
                    super
         | 
| 6 | 
            -
                    @value = typecast(@value)
         | 
| 7 | 
            -
                  end
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                  def dump_default
         | 
| 10 | 
            -
                    %{"#{super}"}
         | 
| 11 | 
            -
                  end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                  private
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                  def typecast(value)
         | 
| 16 | 
            -
                    case value
         | 
| 17 | 
            -
                      when '0', 'false', 'f', 'n', false
         | 
| 18 | 
            -
                        false
         | 
| 19 | 
            -
                      when '1', 'true', 't', 'y', true
         | 
| 20 | 
            -
                        true
         | 
| 21 | 
            -
                      else
         | 
| 22 | 
            -
                        value
         | 
| 23 | 
            -
                    end
         | 
| 24 | 
            -
                  end
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
              end
         | 
| 27 | 
            -
            end
         | 
    
        data/lib/kafo/params/hash.rb
    DELETED
    
    | @@ -1,38 +0,0 @@ | |
| 1 | 
            -
            module Kafo
         | 
| 2 | 
            -
              module Params
         | 
| 3 | 
            -
                class Hash < Param
         | 
| 4 | 
            -
                  def value=(value)
         | 
| 5 | 
            -
                    super
         | 
| 6 | 
            -
                    if @value == ['EMPTY_HASH']
         | 
| 7 | 
            -
                      @value = {}
         | 
| 8 | 
            -
                    else
         | 
| 9 | 
            -
                      @value = typecast(@value)
         | 
| 10 | 
            -
                    end
         | 
| 11 | 
            -
                  end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                  def multivalued?
         | 
| 14 | 
            -
                    true
         | 
| 15 | 
            -
                  end
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                  def condition_value
         | 
| 18 | 
            -
                    value.inspect
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                  private
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                  def typecast(value)
         | 
| 24 | 
            -
                    if value.nil?
         | 
| 25 | 
            -
                      nil
         | 
| 26 | 
            -
                    elsif value.is_a?(::Hash)
         | 
| 27 | 
            -
                      value
         | 
| 28 | 
            -
                    else
         | 
| 29 | 
            -
                      value = [value].flatten
         | 
| 30 | 
            -
                      ::Hash[value.map { |v| v.split(':', 2) }]
         | 
| 31 | 
            -
                    end
         | 
| 32 | 
            -
                  rescue NoMethodError => e
         | 
| 33 | 
            -
                    KafoConfigure.logger.warn "Could not typecast #{value} for parameter #{name}, defaulting to {}"
         | 
| 34 | 
            -
                    return {}
         | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
                end
         | 
| 37 | 
            -
              end
         | 
| 38 | 
            -
            end
         | 
    
        data/lib/kafo/params/integer.rb
    DELETED
    
    | @@ -1,19 +0,0 @@ | |
| 1 | 
            -
            module Kafo
         | 
| 2 | 
            -
              module Params
         | 
| 3 | 
            -
                class Integer < Param
         | 
| 4 | 
            -
                  def value=(value)
         | 
| 5 | 
            -
                    super
         | 
| 6 | 
            -
                    @value = typecast(@value)
         | 
| 7 | 
            -
                  end
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                  private
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                  def typecast(value)
         | 
| 12 | 
            -
                    value.nil? ? nil : value.to_i
         | 
| 13 | 
            -
                  rescue NoMethodError => e
         | 
| 14 | 
            -
                    KafoConfigure.logger.warn "Could not typecast #{value} for parameter #{name}, defaulting to 0"
         | 
| 15 | 
            -
                    return 0
         | 
| 16 | 
            -
                  end
         | 
| 17 | 
            -
                end
         | 
| 18 | 
            -
              end
         | 
| 19 | 
            -
            end
         |