require 'metamodels/uml13_metamodel' require 'rgen/transformer' require 'rgen/ecore/ecore' require 'rgen/array_extensions' class UML13ToECore < RGen::Transformer include RGen::ECore # Options: # # :reference_filter: # a proc which receives an AssociationEnd or a Dependency and should return # true or false, depending on if a referece should be created for it or not # def initialize(*args) options = {} if args.last.is_a?(Hash) options = args.pop end @reference_filter = options[:reference_filter] || proc do |e| if e.is_a?(UML13::AssociationEnd) otherEnd = e.association.connection.find{|ae| ae != e} otherEnd.name && otherEnd.name.size > 0 else false end end super(*args) end def transform trans(:class => UML13::Class) end transform UML13::Model, :to => EPackage do trans(ownedClassOrPackage) { :name => name && name.strip } end transform UML13::Package, :to => EPackage do trans(ownedClassOrPackage) { :name => name && name.strip, :eSuperPackage => trans(namespace.is_a?(UML13::Package) ? namespace : nil) } end method :ownedClassOrPackage do ownedElement.select{|e| e.is_a?(UML13::Package) || e.is_a?(UML13::Class)} end transform UML13::Class, :to => EClass do { :name => name && name.strip, :abstract => isAbstract, :ePackage => trans(namespace.is_a?(UML13::Package) ? namespace : nil), :eStructuralFeatures => trans(feature.select{|f| f.is_a?(UML13::Attribute)} + associationEnd + clientDependency), :eOperations => trans(feature.select{|f| f.is_a?(UML13::Operation)}), :eSuperTypes => trans(generalization.parent + clientDependency.select{|d| d.stereotype && d.stereotype.name == "implements"}.supplier), :eAnnotations => createAnnotations(taggedValue) } end transform UML13::Interface, :to => EClass do { :name => name && name.strip, :abstract => isAbstract, :ePackage => trans(namespace.is_a?(UML13::Package) ? namespace : nil), :eStructuralFeatures => trans(feature.select{|f| f.is_a?(UML13::Attribute)} + associationEnd), :eOperations => trans(feature.select{|f| f.is_a?(UML13::Operation)}), :eSuperTypes => trans(generalization.parent)} end transform UML13::Attribute, :to => EAttribute do { :name => name && name.strip, :eType => trans(getType), :lowerBound => (multiplicity && multiplicity.range.first.lower && multiplicity.range.first.lower.to_i) || 0, :upperBound => (multiplicity && multiplicity.range.first.upper && multiplicity.range.first.upper.gsub('*','-1').to_i) || 1, :eAnnotations => createAnnotations(taggedValue) } end transform UML13::DataType, :to => EDataType do { :name => name && name.strip, :ePackage => trans(namespace.is_a?(UML13::Package) ? namespace : nil), :eAnnotations => createAnnotations(taggedValue) } end transform UML13::Operation, :to => EOperation do { :name => name && name.strip } end transform UML13::AssociationEnd, :to => EReference, :if => :isReference do otherEnd = association.connection.find{|ae| ae != @current_object} { :eType => trans(otherEnd.type), :name => otherEnd.name && otherEnd.name.strip, :eOpposite => trans(otherEnd), :lowerBound => (otherEnd.multiplicity && otherEnd.multiplicity.range.first.lower && otherEnd.multiplicity.range.first.lower.to_i) || 0, :upperBound => (otherEnd.multiplicity && otherEnd.multiplicity.range.first.upper && otherEnd.multiplicity.range.first.upper.gsub('*','-1').to_i) || 1, :containment => (aggregation == :composite), :eAnnotations => createAnnotations(association.taggedValue) } end transform UML13::Dependency, :to => EReference, :if => :isReference do { :eType => trans(supplier.first), :name => name, :lowerBound => 0, :upperBound => 1, :containment => false, :eAnnotations => createAnnotations(taggedValue) } end method :isReference do @reference_filter.call(@current_object) end def createAnnotations(taggedValues) if taggedValues.size > 0 [ EAnnotation.new(:details => trans(taggedValues)) ] else [] end end transform UML13::TaggedValue, :to => EStringToStringMapEntry do { :key => tag, :value => value} end end