# File lib/rgen/metamodel_builder/builder_extensions.rb, line 464
  def build_derived_method(name, props, kind)
    raise "Implement method #{name}_derived instead of method #{name}" \
      if (public_instance_methods+protected_instance_methods+private_instance_methods).include?(name)
    @@derived_builder ||= ERB.new "\ndef get<%= firstToUpper(name) %>\nraise \"Derived feature requires public implementation of method <%= name %>_derived\" \\\nunless respond_to?(:<%= name+\"_derived\" %>)\nval = <%= name %>_derived\n<% if kind == :many %>\nraise _assignmentTypeError(self,val,Enumerable) unless val && val.is_a?(Enumerable)\nval.each do |v|\n<%= type_check_code(\"v\", props) %>\nend\n<% else %>\n<%= type_check_code(\"val\", props) %>\n<% end %>\nval\nend\n<% if name != \"class\" %>\nalias <%= name %> get<%= firstToUpper(name) %>\n<% end %>\n#TODO final_method :<%= name %>\n\n"
    self::ClassModule.module_eval(@@derived_builder.result(binding))
  end

  def check_default_value_literal(literal, props)
    return if literal.nil? || props.impl_type == String
    if props.impl_type == Integer
      unless literal =~ /^\d+$/
        raise StandardError.new("Property #{props.value(:name)} can not take value #{literal}, expected an Integer")
      end
    elsif props.impl_type == Float
      unless literal =~ /^\d+\.\d+$/
        raise StandardError.new("Property #{props.value(:name)} can not take value #{literal}, expected a Float")
      end
    elsif props.impl_type == RGen::MetamodelBuilder::DataTypes::Boolean
      unless ["true", "false"].include?(literal)
        raise StandardError.new("Property #{props.value(:name)} can not take value #{literal}, expected true or false")
      end
    elsif props.impl_type.is_a?(RGen::MetamodelBuilder::DataTypes::Enum)
      unless props.impl_type.literals.include?(literal.to_sym)
        raise StandardError.new("Property #{props.value(:name)} can not take value #{literal}, expected one of #{props.impl_type.literals_as_strings.join(', ')}")
      end
    else
      raise StandardError.new("Unkown type "+props.impl_type.to_s)
    end
  end
  
  def type_check_code(varname, props)
    code = ""
    if props.impl_type.is_a?(Class)
      code << "unless #{varname}.nil? || #{varname}.is_a?(#{props.impl_type}) || #{varname}.is_a?(MMGeneric)"
      code << " || #{varname}.is_a?(BigDecimal)" if props.impl_type == Float && defined?(BigDecimal)
      code << "\n"
      expected = props.impl_type.to_s
    elsif props.impl_type.is_a?(RGen::MetamodelBuilder::DataTypes::Enum)
      code << "unless #{varname}.nil? || [#{props.impl_type.literals_as_strings.join(',')}].include?(#{varname}) || #{varname}.is_a?(MMGeneric)\n"
      expected = "["+props.impl_type.literals_as_strings.join(',')+"]"
    else
      raise StandardError.new("Unkown type "+props.impl_type.to_s)
    end
    code << "raise _assignmentTypeError(self,#{varname},\"#{expected}\")\n"
    code << "end"
    code    
  end  
  
  def _ownProps(props)
    Hash[*(props.select{|k,v| !(k.to_s =~ /^opposite_/)}.flatten)]
  end

  def _oppositeProps(props)
    r = {}
    props.each_pair do |k,v|
      if k.to_s =~ /^opposite_(.*)$/
        r[$1.to_sym] = v
      end
    end
    r
  end

  def _setManyUpperBound(props)
    props[:upperBound] = -1 unless props[:upperBound].is_a?(Integer) && props[:upperBound] > 1
    props
  end
    
end