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