This module provides methods which can be used to setup a metamodel
element. The module is used to extend
MetamodelBuilder::MMBase, i.e. add the module’s
methods as class methods.
MetamodelBuilder::MMBase should be used as a start for new metamodel elements. See MetamodelBuilder for an example.
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 263 def _abstract_class @abstract || false end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 251 def _add_metamodel_description(desc) # :nodoc @metamodel_description ||= [] @metamodelDescriptionByName ||= {} @metamodel_description.delete(@metamodelDescriptionByName[desc.value(:name)]) @metamodel_description << desc @metamodelDescriptionByName[desc.value(:name)] = desc end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 259 def abstract @abstract = true end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 161 def contains_many(target_role, target_class, own_role, raw_props={}, &block) props1 = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({ :name=>target_role, :containment=>true}))) props2 = Intermediate::Reference.new(self, _oppositeProps(raw_props).merge({ :name=>own_role, :upperBound=>1, :containment=>false})) FeatureBlockEvaluator.eval(block, props1, props2) _build_internal(props1, props2) end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 123 def contains_many_uni(role, target_class=nil, raw_props={}, &block) props = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({ :name=>role, :containment=>true}))) raise "No opposite available" unless _oppositeProps(raw_props).empty? FeatureBlockEvaluator.eval(block, props) _build_internal(props) end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 238 def contains_one(target_role, target_class, own_role, raw_props={}, &block) props1 = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({ :name=>target_role, :upperBound=>1, :containment=>true})) props2 = Intermediate::Reference.new(self, _oppositeProps(raw_props).merge({ :name=>own_role, :upperBound=>1, :containment=>false})) FeatureBlockEvaluator.eval(block, props1, props2) _build_internal(props1, props2) end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 115 def contains_one_uni(role, target_class=nil, raw_props={}, &block) props = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({ :name=>role, :upperBound=>1, :containment=>true})) raise "No opposite available" unless _oppositeProps(raw_props).empty? FeatureBlockEvaluator.eval(block, props) _build_internal(props) end
Add an attribute which can hold a single value. ‘role’ specifies the name which is used to access the attribute. ‘target_class’ specifies the type of objects which can be held by this attribute. If no target class is given, String will be default.
This class method adds the following instance methods, where ‘role’ is to be replaced by the given role name:
class#role # getter class#role=(value) # setter
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 48 def has_attr(role, target_class=nil, raw_props={}, &block) props = Intermediate::Attribute.new(target_class, _ownProps(raw_props).merge({ :name=>role, :upperBound=>1})) raise "No opposite available" unless _oppositeProps(raw_props).empty? FeatureBlockEvaluator.eval(block, props) _build_internal(props) end
Add an unidirectional many association. ‘role’ specifies the name which is used to access the attribute. ‘target_class’ is optional and can be used to fix the type of objects which can be referenced by this association.
This class method adds the following instance methods, where ‘role’ is to be replaced by the given role name:
class#addRole(value, index=-1) class#removeRole(value) class#role # getter, returns an array
Note that the first letter of the role name is turned into an uppercase for the add and remove methods.
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 107 def has_many(role, target_class=nil, raw_props={}, &block) props = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({ :name=>role, :containment=>false}))) raise "No opposite available" unless _oppositeProps(raw_props).empty? FeatureBlockEvaluator.eval(block, props) _build_internal(props) end
Add an attribute which can hold multiple values. ‘role’ specifies the name which is used to access the attribute. ‘target_class’ specifies the type of objects which can be held by this attribute. If no target class is given, String will be default.
This class method adds the following instance methods, where ‘role’ is to be replaced by the given role name:
class#addRole(value, index=-1) class#removeRole(value) class#role # getter, returns an array class#role= # setter, sets multiple values at once
Note that the first letter of the role name is turned into an uppercase for the add and remove methods.
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 69 def has_many_attr(role, target_class=nil, raw_props={}, &block) props = Intermediate::Attribute.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({ :name=>role}))) raise "No opposite available" unless _oppositeProps(raw_props).empty? FeatureBlockEvaluator.eval(block, props) _build_internal(props) end
Add a single unidirectional association. ‘role’ specifies the name which is used to access the association. ‘target_class’ specifies the type of objects which can be held by this association.
This class method adds the following instance methods, where ‘role’ is to be replaced by the given role name:
class#role # getter class#role=(value) # setter
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 86 def has_one(role, target_class=nil, raw_props={}, &block) props = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({ :name=>role, :upperBound=>1, :containment=>false})) raise "No opposite available" unless _oppositeProps(raw_props).empty? FeatureBlockEvaluator.eval(block, props) _build_internal(props) end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 267 def inherited(c) c.send(:include, c.const_set(:ClassModule, Module.new)) MetamodelBuilder::ConstantOrderHelper.classCreated(c) end
Add a bidirectional many-to-many association between two classes. The class this method is called on is refered to as own_class in the following.
Instances of own_class can use ‘own_role’ to access many associated instances of type ‘target_class’. Instances of ‘target_class’ can use ‘target_role’ to access many associated instances of own_class.
This class method adds the following instance methods where ‘ownRole’ and ‘targetRole’ are to be replaced by the given role names:
own_class#addOwnRole(value, index=-1) own_class#removeOwnRole(value) own_class#ownRole target_class#addTargetRole target_class#removeTargetRole=(value) target_class#targetRole
Note that the first letter of the role name is turned into an uppercase for the add and remove methods.
When an element is added on either side, this element also receives the element is is added to as a new element.
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 202 def many_to_many(target_role, target_class, own_role, raw_props={}, &block) props1 = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({ :name=>target_role, :containment=>false}))) props2 = Intermediate::Reference.new(self, _setManyUpperBound(_oppositeProps(raw_props).merge({ :name=>own_role, :containment=>false}))) FeatureBlockEvaluator.eval(block, props1, props2) _build_internal(props1, props2) end
This is the inverse of #one_to_many provided for convenience.
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 171 def many_to_one(target_role, target_class, own_role, raw_props={}, &block) props1 = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({ :name=>target_role, :upperBound=>1, :containment=>false})) props2 = Intermediate::Reference.new(self, _setManyUpperBound(_oppositeProps(raw_props).merge({ :name=>own_role, :containment=>false}))) FeatureBlockEvaluator.eval(block, props1, props2) _build_internal(props1, props2) end
Add a bidirectional one-to-many association between two classes. The class this method is called on is refered to as own_class in the following.
Instances of own_class can use ‘own_role’ to access many associated instances of type ‘target_class’. Instances of ‘target_class’ can use ‘target_role’ to access one associated instance of own_class.
This class method adds the following instance methods where ‘ownRole’ and ‘targetRole’ are to be replaced by the given role names:
own_class#addOwnRole(value, index=-1) own_class#removeOwnRole(value) own_class#ownRole target_class#targetRole target_class#targetRole=(value)
Note that the first letter of the role name is turned into an uppercase for the add and remove methods.
When an element is added/set on either side, this element also receives the element is is added to as a new element.
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 152 def one_to_many(target_role, target_class, own_role, raw_props={}, &block) props1 = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({ :name=>target_role, :containment=>false}))) props2 = Intermediate::Reference.new(self, _oppositeProps(raw_props).merge({ :name=>own_role, :upperBound=>1, :containment=>false})) FeatureBlockEvaluator.eval(block, props1, props2) _build_internal(props1, props2) end
Add a bidirectional one-to-one association between two classes. The class this method is called on is refered to as own_class in the following.
Instances of own_class can use ‘own_role’ to access one associated instance of type ‘target_class’. Instances of ‘target_class’ can use ‘target_role’ to access one associated instance of own_class.
This class method adds the following instance methods where ‘ownRole’ and ‘targetRole’ are to be replaced by the given role names:
own_class#ownRole own_class#ownRole=(value) target_class#targetRole target_class#targetRole=(value)
When an element is set on either side, this element also receives the element is is added to as the new element.
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 229 def one_to_one(target_role, target_class, own_role, raw_props={}, &block) props1 = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({ :name=>target_role, :upperBound=>1, :containment=>false})) props2 = Intermediate::Reference.new(self, _oppositeProps(raw_props).merge({ :name=>own_role, :upperBound=>1, :containment=>false})) FeatureBlockEvaluator.eval(block, props1, props2) _build_internal(props1, props2) end
Central builder method
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 276 def _build_internal(props1, props2=nil) _add_metamodel_description(props1) if props1.many? _build_many_methods(props1, props2) else _build_one_methods(props1, props2) end if props2 # this is a bidirectional reference props1.opposite, props2.opposite = props2, props1 other_class = props1.impl_type other_class._add_metamodel_description(props2) raise "Internal error: second description must be a reference description" \ unless props2.reference? if props2.many? other_class._build_many_methods(props2, props1) else other_class._build_one_methods(props2, props1) end end end # To-One association methods # def _build_one_methods(props, other_props=nil) name = props.value(:name) other_role = other_props && other_props.value(:name) if props.value(:derived) build_derived_method(name, props, :one) else @@one_read_builder ||= ERB.new <<-CODE def get<%= firstToUpper(name) %> <% if !props.reference? && props.value(:defaultValueLiteral) %> <% defVal = props.value(:defaultValueLiteral) %> <% check_default_value_literal(defVal, props) %> <% defVal = '"'+defVal+'"' if props.impl_type == String %> <% defVal = ':'+defVal if props.impl_type.is_a?(DataTypes::Enum) && props.impl_type != DataTypes::Boolean %> (defined? @<%= name %>) ? @<%= name %> : <%= defVal %> <% else %> @<%= name %> <% end %> end <% if name != "class" %> alias <%= name %> get<%= firstToUpper(name) %> <% end %> CODE self::ClassModule.module_eval(@@one_read_builder.result(binding)) end if props.value(:changeable) @@one_write_builder ||= ERB.new <<-CODE def set<%= firstToUpper(name) %>(val) return if (defined? @<%= name %>) && val == @<%= name %> <%= type_check_code("val", props) %> oldval = @<%= name %> @<%= name %> = val <% if other_role %> oldval._unregister<%= firstToUpper(other_role) %>(self) unless oldval.nil? || oldval.is_a?(MMGeneric) val._register<%= firstToUpper(other_role) %>(self) unless val.nil? || val.is_a?(MMGeneric) <% end %> <% if props.reference? && props.value(:containment) %> val._set_container(self, :<%= name %>) unless val.nil? oldval._set_container(nil, nil) unless oldval.nil? <% end %> end alias <%= name %>= set<%= firstToUpper(name) %> def _register<%= firstToUpper(name) %>(val) <% if other_role %> @<%= name %>._unregister<%= firstToUpper(other_role) %>(self) unless @<%= name %>.nil? || @<%= name %>.is_a?(MMGeneric) <% end %> <% if props.reference? && props.value(:containment) %> @<%= name %>._set_container(nil, nil) unless @<%= name %>.nil? val._set_container(self, :<%= name %>) unless val.nil? <% end %> @<%= name %> = val end def _unregister<%= firstToUpper(name) %>(val) <% if props.reference? && props.value(:containment) %> @<%= name %>._set_container(nil, nil) unless @<%= name %>.nil? <% end %> @<%= name %> = nil end CODE self::ClassModule.module_eval(@@one_write_builder.result(binding)) end end # To-Many association methods # def _build_many_methods(props, other_props=nil) name = props.value(:name) other_role = other_props && other_props.value(:name) if props.value(:derived) build_derived_method(name, props, :many) else @@many_read_builder ||= ERB.new <<-CODE def get<%= firstToUpper(name) %> ( @<%= name %> ? @<%= name %>.dup : [] ) end <% if name != "class" %> alias <%= name %> get<%= firstToUpper(name) %> <% end %> CODE self::ClassModule.module_eval(@@many_read_builder.result(binding)) end if props.value(:changeable) @@many_write_builder ||= ERB.new <<-CODE def add<%= firstToUpper(name) %>(val, index=-1) @<%= name %> = [] unless @<%= name %> return if val.nil? || (val.is_a?(MMBase) || val.is_a?(MMGeneric)) && @<%= name %>.any? {|e| e.equal?(val)} <%= type_check_code("val", props) %> @<%= name %>.insert(index, val) <% if other_role %> val._register<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMGeneric) <% end %> <% if props.reference? && props.value(:containment) %> val._set_container(self, :<%= name %>) <% end %> end def remove<%= firstToUpper(name) %>(val) @<%= name %> = [] unless @<%= name %> @<%= name %>.each_with_index do |e,i| if e.equal?(val) @<%= name %>.delete_at(i) <% if props.reference? && props.value(:containment) %> val._set_container(nil, nil) <% end %> <% if other_role %> val._unregister<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMGeneric) <% end %> return end end end def set<%= firstToUpper(name) %>(val) return if val.nil? raise _assignmentTypeError(self, val, Enumerable) unless val.is_a? Enumerable get<%= firstToUpper(name) %>.each {|e| remove<%= firstToUpper(name) %>(e) } @<%= name %> = [] unless @<%= name %> <% if props.reference? %> val.uniq {|elem| elem.object_id }.each {|elem| next if elem.nil? <%= type_check_code("elem", props) %> @<%= name %> << elem <% if other_role %> elem._register<%= firstToUpper(other_role) %>(self) unless elem.is_a?(MMGeneric) <% end %> <% if props.value(:containment) %> elem._set_container(self, :<%= name %>) <% end %> } <% else %> val.each {|elem| <%= type_check_code("elem", props) %> @<%= name %> << elem } <% end %> end alias <%= name %>= set<%= firstToUpper(name) %> def _register<%= firstToUpper(name) %>(val) @<%= name %> = [] unless @<%= name %> @<%= name %>.push val <% if props.reference? && props.value(:containment) %> val._set_container(self, :<%= name %>) <% end %> end def _unregister<%= firstToUpper(name) %>(val) @<%= name %>.delete val <% if props.reference? && props.value(:containment) %> val._set_container(nil, nil) <% end %> end CODE self::ClassModule.module_eval(@@many_write_builder.result(binding)) end end private 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 <<-CODE def get<%= firstToUpper(name) %> raise "Derived feature requires public implementation of method <%= name %>_derived" \ unless respond_to?(:<%= name+"_derived" %>) val = <%= name %>_derived <% if kind == :many %> raise _assignmentTypeError(self,val,Enumerable) unless val && val.is_a?(Enumerable) val.each do |v| <%= type_check_code("v", props) %> end <% else %> <%= type_check_code("val", props) %> <% end %> val end <% if name != "class" %> alias <%= name %> get<%= firstToUpper(name) %> <% end %> #TODO final_method :<%= name %> CODE 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 || props.impl_type == RGen::MetamodelBuilder::DataTypes::Long 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 == RGen::MetamodelBuilder::DataTypes::Long code << "unless #{varname}.nil? || #{varname}.is_a?(Integer) || #{varname}.is_a?(MMGeneric)" code << "\n" expected = "Integer" elsif 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 end
To-Many association methods
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 373 def _build_many_methods(props, other_props=nil) name = props.value(:name) other_role = other_props && other_props.value(:name) if props.value(:derived) build_derived_method(name, props, :many) else @@many_read_builder ||= ERB.new <<-CODE def get<%= firstToUpper(name) %> ( @<%= name %> ? @<%= name %>.dup : [] ) end <% if name != "class" %> alias <%= name %> get<%= firstToUpper(name) %> <% end %> CODE self::ClassModule.module_eval(@@many_read_builder.result(binding)) end if props.value(:changeable) @@many_write_builder ||= ERB.new <<-CODE def add<%= firstToUpper(name) %>(val, index=-1) @<%= name %> = [] unless @<%= name %> return if val.nil? || (val.is_a?(MMBase) || val.is_a?(MMGeneric)) && @<%= name %>.any? {|e| e.equal?(val)} <%= type_check_code("val", props) %> @<%= name %>.insert(index, val) <% if other_role %> val._register<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMGeneric) <% end %> <% if props.reference? && props.value(:containment) %> val._set_container(self, :<%= name %>) <% end %> end def remove<%= firstToUpper(name) %>(val) @<%= name %> = [] unless @<%= name %> @<%= name %>.each_with_index do |e,i| if e.equal?(val) @<%= name %>.delete_at(i) <% if props.reference? && props.value(:containment) %> val._set_container(nil, nil) <% end %> <% if other_role %> val._unregister<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMGeneric) <% end %> return end end end def set<%= firstToUpper(name) %>(val) return if val.nil? raise _assignmentTypeError(self, val, Enumerable) unless val.is_a? Enumerable get<%= firstToUpper(name) %>.each {|e| remove<%= firstToUpper(name) %>(e) } @<%= name %> = [] unless @<%= name %> <% if props.reference? %> val.uniq {|elem| elem.object_id }.each {|elem| next if elem.nil? <%= type_check_code("elem", props) %> @<%= name %> << elem <% if other_role %> elem._register<%= firstToUpper(other_role) %>(self) unless elem.is_a?(MMGeneric) <% end %> <% if props.value(:containment) %> elem._set_container(self, :<%= name %>) <% end %> } <% else %> val.each {|elem| <%= type_check_code("elem", props) %> @<%= name %> << elem } <% end %> end alias <%= name %>= set<%= firstToUpper(name) %> def _register<%= firstToUpper(name) %>(val) @<%= name %> = [] unless @<%= name %> @<%= name %>.push val <% if props.reference? && props.value(:containment) %> val._set_container(self, :<%= name %>) <% end %> end def _unregister<%= firstToUpper(name) %>(val) @<%= name %>.delete val <% if props.reference? && props.value(:containment) %> val._set_container(nil, nil) <% end %> end CODE self::ClassModule.module_eval(@@many_write_builder.result(binding)) end end
To-One association methods
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 300 def _build_one_methods(props, other_props=nil) name = props.value(:name) other_role = other_props && other_props.value(:name) if props.value(:derived) build_derived_method(name, props, :one) else @@one_read_builder ||= ERB.new <<-CODE def get<%= firstToUpper(name) %> <% if !props.reference? && props.value(:defaultValueLiteral) %> <% defVal = props.value(:defaultValueLiteral) %> <% check_default_value_literal(defVal, props) %> <% defVal = '"'+defVal+'"' if props.impl_type == String %> <% defVal = ':'+defVal if props.impl_type.is_a?(DataTypes::Enum) && props.impl_type != DataTypes::Boolean %> (defined? @<%= name %>) ? @<%= name %> : <%= defVal %> <% else %> @<%= name %> <% end %> end <% if name != "class" %> alias <%= name %> get<%= firstToUpper(name) %> <% end %> CODE self::ClassModule.module_eval(@@one_read_builder.result(binding)) end if props.value(:changeable) @@one_write_builder ||= ERB.new <<-CODE def set<%= firstToUpper(name) %>(val) return if (defined? @<%= name %>) && val == @<%= name %> <%= type_check_code("val", props) %> oldval = @<%= name %> @<%= name %> = val <% if other_role %> oldval._unregister<%= firstToUpper(other_role) %>(self) unless oldval.nil? || oldval.is_a?(MMGeneric) val._register<%= firstToUpper(other_role) %>(self) unless val.nil? || val.is_a?(MMGeneric) <% end %> <% if props.reference? && props.value(:containment) %> val._set_container(self, :<%= name %>) unless val.nil? oldval._set_container(nil, nil) unless oldval.nil? <% end %> end alias <%= name %>= set<%= firstToUpper(name) %> def _register<%= firstToUpper(name) %>(val) <% if other_role %> @<%= name %>._unregister<%= firstToUpper(other_role) %>(self) unless @<%= name %>.nil? || @<%= name %>.is_a?(MMGeneric) <% end %> <% if props.reference? && props.value(:containment) %> @<%= name %>._set_container(nil, nil) unless @<%= name %>.nil? val._set_container(self, :<%= name %>) unless val.nil? <% end %> @<%= name %> = val end def _unregister<%= firstToUpper(name) %>(val) <% if props.reference? && props.value(:containment) %> @<%= name %>._set_container(nil, nil) unless @<%= name %>.nil? <% end %> @<%= name %> = nil end CODE self::ClassModule.module_eval(@@one_write_builder.result(binding)) end end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 553 def _oppositeProps(props) r = {} props.each_pair do |k,v| if k.to_s =~ /^opposite_(.*)$/ r[$1.to_sym] = v end end r end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 549 def _ownProps(props) Hash[*(props.select{|k,v| !(k.to_s =~ /^opposite_/)}.flatten)] end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 563 def _setManyUpperBound(props) props[:upperBound] = -1 unless props[:upperBound].is_a?(Integer) && props[:upperBound] > 1 props end
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 476 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 <<-CODE def get<%= firstToUpper(name) %> raise "Derived feature requires public implementation of method <%= name %>_derived" \ unless respond_to?(:<%= name+"_derived" %>) val = <%= name %>_derived <% if kind == :many %> raise _assignmentTypeError(self,val,Enumerable) unless val && val.is_a?(Enumerable) val.each do |v| <%= type_check_code("v", props) %> end <% else %> <%= type_check_code("val", props) %> <% end %> val end <% if name != "class" %> alias <%= name %> get<%= firstToUpper(name) %> <% end %> #TODO final_method :<%= name %> CODE 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 || props.impl_type == RGen::MetamodelBuilder::DataTypes::Long 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 == RGen::MetamodelBuilder::DataTypes::Long code << "unless #{varname}.nil? || #{varname}.is_a?(Integer) || #{varname}.is_a?(MMGeneric)" code << "\n" expected = "Integer" elsif 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
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 504 def check_default_value_literal(literal, props) return if literal.nil? || props.impl_type == String if props.impl_type == Integer || props.impl_type == RGen::MetamodelBuilder::DataTypes::Long 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
# File lib/rgen/metamodel_builder/builder_extensions.rb, line 527 def type_check_code(varname, props) code = "" if props.impl_type == RGen::MetamodelBuilder::DataTypes::Long code << "unless #{varname}.nil? || #{varname}.is_a?(Integer) || #{varname}.is_a?(MMGeneric)" code << "\n" expected = "Integer" elsif 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