rgen 0.2.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.
Files changed (54) hide show
  1. data/CHANGELOG +9 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +73 -0
  4. data/lib/ea/xmi_class_instantiator.rb +45 -0
  5. data/lib/ea/xmi_helper.rb +26 -0
  6. data/lib/ea/xmi_metamodel.rb +19 -0
  7. data/lib/ea/xmi_object_instantiator.rb +42 -0
  8. data/lib/ea/xmi_to_classmodel.rb +78 -0
  9. data/lib/ea/xmi_to_objectmodel.rb +89 -0
  10. data/lib/mmgen/metamodel_generator.rb +19 -0
  11. data/lib/mmgen/mm_ext/uml_classmodel_ext.rb +71 -0
  12. data/lib/mmgen/mmgen.rb +21 -0
  13. data/lib/mmgen/templates/uml_classmodel.tpl +63 -0
  14. data/lib/rgen/array_extensions.rb +23 -0
  15. data/lib/rgen/auto_class_creator.rb +56 -0
  16. data/lib/rgen/environment.rb +57 -0
  17. data/lib/rgen/metamodel_builder.rb +102 -0
  18. data/lib/rgen/metamodel_builder/build_helper.rb +29 -0
  19. data/lib/rgen/metamodel_builder/builder_extensions.rb +191 -0
  20. data/lib/rgen/metamodel_builder/builder_runtime.rb +67 -0
  21. data/lib/rgen/name_helper.rb +18 -0
  22. data/lib/rgen/template_language.rb +169 -0
  23. data/lib/rgen/template_language/directory_template_container.rb +51 -0
  24. data/lib/rgen/template_language/output_handler.rb +84 -0
  25. data/lib/rgen/template_language/template_container.rb +153 -0
  26. data/lib/rgen/template_language/template_helper.rb +26 -0
  27. data/lib/rgen/transformer.rb +316 -0
  28. data/lib/rgen/xml_instantiator/dependency_resolver.rb +23 -0
  29. data/lib/rgen/xml_instantiator/xml_instantiator.rb +78 -0
  30. data/lib/rgen/xml_instantiator/xml_parser.rb +39 -0
  31. data/lib/uml/objectmodel_instantiator.rb +53 -0
  32. data/lib/uml/uml_classmodel.rb +92 -0
  33. data/lib/uml/uml_objectmodel.rb +65 -0
  34. data/test/array_extensions_test.rb +54 -0
  35. data/test/environment_test.rb +47 -0
  36. data/test/metamodel_builder_test.rb +175 -0
  37. data/test/metamodel_generator_test.rb +45 -0
  38. data/test/metamodel_generator_test/TestModel.rb +40 -0
  39. data/test/metamodel_generator_test/expected_result.txt +40 -0
  40. data/test/output_handler_test.rb +40 -0
  41. data/test/rgen_test.rb +13 -0
  42. data/test/template_language_test.rb +46 -0
  43. data/test/template_language_test/expected_result.txt +10 -0
  44. data/test/template_language_test/templates/content/chapter.tpl +5 -0
  45. data/test/template_language_test/templates/index/c/cmod.tpl +1 -0
  46. data/test/template_language_test/templates/index/chapter.tpl +3 -0
  47. data/test/template_language_test/templates/root.tpl +22 -0
  48. data/test/template_language_test/testout.txt +10 -0
  49. data/test/transformer_test.rb +176 -0
  50. data/test/xmi_class_instantiator_test.rb +107 -0
  51. data/test/xmi_instantiator_test/testmodel.eap +0 -0
  52. data/test/xmi_instantiator_test/testmodel.xml +962 -0
  53. data/test/xmi_object_instantiator_test.rb +65 -0
  54. metadata +117 -0
@@ -0,0 +1,9 @@
1
+ =0.1.0 (August 3rd, 2006)
2
+
3
+ * First public release
4
+
5
+ =0.2.0 (September 3rd, 2006)
6
+
7
+ * Added model transformation language (Transformer)
8
+ * Now RGen is distributed as a gem
9
+ * More complete documentation
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006 Martin Thiede
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,73 @@
1
+ == RGen - Ruby Modelling and Generator Framework
2
+
3
+ RGen is a framework supporting Model Driven Software Development (MDSD).
4
+ This means that it helps you build Metamodels, instantiate Models, modify
5
+ and transform Models and finally generate arbitrary textual content from it.
6
+
7
+ RGen features include:
8
+ * Programmatic definition of Metamodels
9
+ * Instantiation of Metamodels, i.e. creation of Models (e.g. from XML)
10
+ * Model Transformations
11
+ * Powerful template based generator language
12
+ * A growing set of included Metamodels, Transformations, Generators:
13
+ * UML Class and Object Diagram Metamodel
14
+ * Instantiation of UML Models from XMI
15
+ * Metamodel Generator generating programmatic Metamodel definitions from UML Class Models
16
+
17
+
18
+ = Download
19
+
20
+ Get the latest release from Rubyforge:
21
+
22
+ http://rubyforge.org/frs/?group_id=1988
23
+
24
+
25
+ = Installation
26
+
27
+ Unpack the release package somewhere to your filesystem.
28
+ Make sure the 'lib' folder is included in the search path (-I) when you run your own scripts.
29
+
30
+ As of version 0.2.0 RGen is also available as a gem.
31
+
32
+
33
+ = Getting started
34
+
35
+ Change to the 'test' folder and run the test suite:
36
+
37
+ test> ruby rgen_test.rb
38
+
39
+
40
+ = Documentation
41
+
42
+ RGen is being documented using rdoc.
43
+ Point your browser to 'doc/index.html' to view the documentation.
44
+
45
+ These are the main parts already documented:
46
+ * RGen::MetamodelBuilder
47
+ * RGen::Transformer
48
+ * RGen::TemplateLanguage
49
+
50
+
51
+ = Examples
52
+
53
+ There are several examples of using RGen within the framework itself.
54
+
55
+ Metamodel Definition:
56
+ lib/uml/uml_classmodel.rb
57
+ lib/uml/uml_objectmodel.rb
58
+
59
+ Instantiation:
60
+ lib/ea/xmi_class_instantiator.rb
61
+ lib/ea/xmi_object_instantiator.rb
62
+
63
+ Transformations:
64
+ lib/ea/xmi_to_classmodel.rb
65
+ lib/ea/xmi_to_objectmodel.rb
66
+
67
+ Generators:
68
+ lib/mmgen/metamodel_generator.rb
69
+
70
+
71
+ = License
72
+
73
+ RGen is released under the MIT license.
@@ -0,0 +1,45 @@
1
+ require 'rgen/xml_instantiator/xml_instantiator'
2
+ require 'rgen/environment'
3
+ require 'uml/uml_classmodel'
4
+ require 'ea/xmi_metamodel'
5
+
6
+ # This module can be used to instantiate an UMLClassModel from an XMI description.
7
+ # It should be mixed into the using class.
8
+ #
9
+ # Here is an example:
10
+ #
11
+ # include XMIClassInstantiator
12
+ #
13
+ # envUML = RGen::Environment.new
14
+ # File.open(MODEL_DIR+"/testmodel.xml") { |f|
15
+ # instantiateUMLClassModel(envUML, f.read)
16
+ # }
17
+ #
18
+ # # now use the newly created UML model
19
+ # envUML.find(:class => UMLClassModel::UMLClass).each { |c|
20
+ # puts c.name
21
+ # }
22
+ #
23
+ # This module relies on XmiToClassmodel to do the actual transformation.
24
+ #
25
+ module XMIClassInstantiator
26
+
27
+ include UMLClassModel
28
+
29
+ # This method does the actual work.
30
+ def instantiateUMLClassModel(envOut, str)
31
+ inst = RGen::XMLInstantiator.new(XMIMetaModel, true) do |i|
32
+ i.resolveById("xmi_id","type")
33
+ i.resolveById("xmi_id","subtype")
34
+ i.resolveById("xmi_id","supertype")
35
+ end
36
+
37
+ envXMI = RGen::Environment.new
38
+ inst.instantiate(envXMI, str)
39
+
40
+ require 'ea/xmi_to_classmodel'
41
+
42
+ XmiToClassmodel.new(envXMI,envOut).transform
43
+ end
44
+
45
+ end
@@ -0,0 +1,26 @@
1
+ require 'rgen/metamodel_builder'
2
+
3
+ module RGen
4
+
5
+ module XMIHelper
6
+
7
+ class MapHelper
8
+ def initialize(keyMethod,valueMethod,elements)
9
+ @keyMethod, @valueMethod, @elements = keyMethod, valueMethod, elements
10
+ end
11
+ def [](key)
12
+ return @elements.select{|e| e.send(@keyMethod) == key}.first.send(@valueMethod) rescue NoMethodError
13
+ nil
14
+ end
15
+ end
16
+
17
+ class TaggedValueHelper < MapHelper
18
+ def initialize(element)
19
+ super('tag','value',element.UML_ModelElement_taggedValue.UML_TaggedValue)
20
+ end
21
+ end
22
+
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,19 @@
1
+
2
+ module XMIMetaModel
3
+ include RGen::MetamodelBuilder
4
+ class UML_Classifier_feature < MMBase
5
+ end
6
+ class UML_Class < MMBase
7
+ end
8
+ class UML_Operation < MMBase
9
+ end
10
+ class UML_Generalization < MMBase
11
+ end
12
+ class UML_ModelElement_stereotype < MMBase
13
+ end
14
+ UML_Classifier_feature.one_to_many 'UML_Operation', UML_Operation, '_p_UML_Classifier_feature'
15
+ UML_Class.one_to_many 'UML_ModelElement_stereotype', UML_ModelElement_stereotype, '_p_UML_Class'
16
+ # UML_Class.one_to_many 'UML_Generalization_supertype', UML_Generalization, 'supertype_UML_Class'
17
+ # UML_Class.one_to_many 'UML_Generalization_subtype', UML_Generalization, 'subtype_UML_Class'
18
+ end
19
+
@@ -0,0 +1,42 @@
1
+ require 'rgen/xml_instantiator/xml_instantiator'
2
+ require 'rgen/environment'
3
+ require 'uml/uml_objectmodel'
4
+ require 'ea/xmi_metamodel'
5
+
6
+ # This module can be used to instantiate an UMLObjectModel from an XMI description.
7
+ # It should be mixed into the using class.
8
+ #
9
+ # Here is an example:
10
+ #
11
+ # include XMIObjectInstantiator
12
+ #
13
+ # envUML = RGen::Environment.new
14
+ # File.open(MODEL_DIR+"/testmodel.xml") { |f|
15
+ # instantiateUMLObjectModel(envUML, f.read)
16
+ # }
17
+ #
18
+ # # now use the newly created UML model
19
+ # envUML.find(:class => UMLObjectModel::UMLObject).each { |o|
20
+ # puts o.name
21
+ # }
22
+ #
23
+ # This module relies on XmiToObjectmodel to do the actual transformation.
24
+ #
25
+ module XMIObjectInstantiator
26
+
27
+ include UMLObjectModel
28
+
29
+ def instantiateUMLObjectModel(envOut, str)
30
+ inst = RGen::XMLInstantiator.new(XMIMetaModel, true) do |i|
31
+ i.resolveById("xmi_id","type")
32
+ end
33
+
34
+ envXMI = RGen::Environment.new
35
+ inst.instantiate(envXMI, str)
36
+
37
+ require 'ea/xmi_to_objectmodel'
38
+
39
+ XmiToObjectmodel.new(envXMI,envOut).transform
40
+ end
41
+
42
+ end
@@ -0,0 +1,78 @@
1
+ require 'rgen/transformer'
2
+ require 'ea/xmi_helper'
3
+ require 'ea/xmi_metamodel'
4
+ require 'uml/uml_classmodel'
5
+ require 'rgen/array_extensions'
6
+
7
+ # This class is a RGen::Transformer working on an input and output Environment.
8
+ # It creates an UMLClassModel from an XMI Model instantiated by a
9
+ # RGen::XMLInstantiator.
10
+ #
11
+ # See description of RGen::XMLInstantiator for details about the XMI (meta-)model.
12
+ # See UMLClassModel for details about the UML Class (meta-)model.
13
+ class XmiToClassmodel < RGen::Transformer
14
+ include UMLClassModel
15
+ include RGen::XMIHelper
16
+
17
+ # Do the actual transformation.
18
+ # Input and output environment have to be provided to the transformer constructor.
19
+ def transform
20
+ trans(:class => XMIMetaModel::UML_Class)
21
+ end
22
+
23
+ transform XMIMetaModel::UML_Package, :to => UMLPackage do
24
+ { :name => name,
25
+ :superpackage => trans(_p_UML_Namespace_ownedElement._p_UML_Package) }
26
+ end
27
+
28
+ transform XMIMetaModel::UML_Attribute, :to => UMLAttribute do
29
+ tv = TaggedValueHelper.new(@current_object)
30
+ { :name => name, :type => tv['type'] }
31
+ end
32
+
33
+ transform XMIMetaModel::UML_Operation, :to => UMLOperation do
34
+ { :name => name }
35
+ end
36
+
37
+ transform XMIMetaModel::UML_TaggedValue, :to => UMLTaggedValue do
38
+ { :tag => tag, :value => value }
39
+ end
40
+
41
+ transform XMIMetaModel::UML_Class, :to => UMLClass do
42
+ { :name => name,
43
+ :package => trans(_p_UML_Namespace_ownedElement._p_UML_Package),
44
+ :attributes => trans(getUML_Classifier_feature.UML_Attribute),
45
+ :operations => trans(getUML_Classifier_feature.UML_Operation),
46
+ :taggedvalues => trans(getUML_ModelElement_taggedValue.UML_TaggedValue),
47
+ :stereotypes => getUML_ModelElement_stereotype.UML_Stereotype.name,
48
+ :subclasses => trans(getUML_Generalization_supertype.subtype_UML_Class),
49
+ :assocEnds => trans(getUML_AssociationEnd_type)}
50
+ end
51
+
52
+ transform XMIMetaModel::UML_Association, :to => :scAssociationClass do
53
+ { :endA => trans(scAssocEnds[0]),
54
+ :endB => trans(scAssocEnds[1]) }
55
+ end
56
+
57
+ method :scAssocEnds do
58
+ getUML_Association_connection.UML_AssociationEnd
59
+ end
60
+
61
+ method :scAssociationClass do
62
+ (scAssocEnds[0].aggregation == 'composite' or
63
+ scAssocEnds[1].aggregation == 'composite' ?
64
+ UMLAggregation : UMLAssociation )
65
+ end
66
+
67
+ transform XMIMetaModel::UML_AssociationEnd, :to => UMLAssociationEnd do
68
+ # since we don't want to figure out if we are end A or end B,
69
+ # we let the association transformer do the work
70
+ trans(_p_UML_Association_connection._p_UML_Association)
71
+ { :clazz => trans(type_UML_Class),
72
+ :role => name,
73
+ :multiplicity => multiplicity,
74
+ :composite => (aggregation == 'composite'),
75
+ :navigable => (isNavigable == 'true') }
76
+ end
77
+
78
+ end
@@ -0,0 +1,89 @@
1
+ require 'rgen/transformer'
2
+ require 'ea/xmi_helper'
3
+ require 'ea/xmi_metamodel'
4
+ require 'uml/uml_objectmodel'
5
+ require 'rgen/array_extensions'
6
+
7
+ # This class is a RGen::Transformer working on an input and output Environment.
8
+ # It creates an UMLObjectModel from an XMI Model instantiated by a
9
+ # RGen::XMLInstantiator.
10
+ #
11
+ # See description of RGen::XMLInstantiator for details about the XMI (meta-)model.
12
+ # See UMLObjectModel for details about the UML Object (meta-)model.
13
+ class XmiToObjectmodel < RGen::Transformer
14
+ include UMLObjectModel
15
+ include RGen::XMIHelper
16
+
17
+ # Do the actual transformation.
18
+ # Input and output environment have to be provided to the transformer constructor.
19
+ def transform
20
+ trans(:class => XMIMetaModel::UML_ClassifierRole)
21
+ end
22
+
23
+ transform XMIMetaModel::UML_Package, :to => UMLPackage do
24
+ { :name => name,
25
+ :superpackage => trans(_p_UML_Namespace_ownedElement._p_UML_Package) }
26
+ end
27
+
28
+ transform XMIMetaModel::UML_ClassifierRole, :to => UMLObject, :if => :isEASTypeObject do
29
+ trans(getUML_AssociationEndRole_type._p_UML_Association_connection._p_UML_AssociationRole)
30
+ trans(getUML_AssociationEnd_type._p_UML_Association_connection._p_UML_Association)
31
+ taggedValues = TaggedValueHelper.new(@current_object)
32
+ { :name => name,
33
+ :classname => taggedValues['classname'],
34
+ :attributeSettings => createAttributeSettings(taggedValues['runstate']),
35
+ :package => trans(_p_UML_Namespace_ownedElement._p_UML_Collaboration._p_UML_Namespace_ownedElement._p_UML_Package) }
36
+ end
37
+
38
+ method :isEASTypeObject do
39
+ taggedValues = TaggedValueHelper.new(@current_object)
40
+ taggedValues['ea_stype'] == 'Object'
41
+ end
42
+
43
+ def createAttributeSettings(runstate)
44
+ return [] unless runstate
45
+ result = []
46
+ as = nil
47
+ runstate.split(';').each do |t|
48
+ if t == '@VAR'
49
+ as = @env_out.new UMLAttributeSetting
50
+ result << as
51
+ elsif t =~ /(\w+)=(\w+)/
52
+ as.name = $2 if $1 == 'Variable'
53
+ as.value = $2 if $1 == 'Value'
54
+ end
55
+ end
56
+ result
57
+ end
58
+
59
+ transform XMIMetaModel::UML_AssociationRole, :to => UMLAssociation, :if => :isEATypeAssociation do
60
+ ends = getUML_Association_connection.UML_AssociationEndRole
61
+ { :endA => trans(ends[0]), :endB => trans(ends[1])}
62
+ end
63
+
64
+ method :isEATypeAssociation do
65
+ taggedValues = TaggedValueHelper.new(@current_object)
66
+ taggedValues['ea_type'] == 'Association'
67
+ end
68
+
69
+ transform XMIMetaModel::UML_Association, :to => UMLAggregation do
70
+ ends = getUML_Association_connection.UML_AssociationEnd
71
+ { :endA => trans(ends[0]), :endB => trans(ends[1])}
72
+ end
73
+
74
+ transform XMIMetaModel::UML_AssociationEndRole, :to => UMLAssociationEnd do
75
+ buildAssociationEnd
76
+ end
77
+
78
+ transform XMIMetaModel::UML_AssociationEnd, :to => UMLAssociationEnd do
79
+ buildAssociationEnd
80
+ end
81
+
82
+ method :buildAssociationEnd do
83
+ { :object => trans(type_UML_ClassifierRole),
84
+ :role => name,
85
+ :composite => (aggregation == 'composite'),
86
+ :navigable => (isNavigable == 'true') }
87
+ end
88
+
89
+ end
@@ -0,0 +1,19 @@
1
+ require 'rgen/environment'
2
+ require 'rgen/template_language'
3
+ require 'uml/uml_classmodel'
4
+ require 'mmgen/mm_ext/uml_classmodel_ext'
5
+
6
+ module MMGen
7
+
8
+ module MetamodelGenerator
9
+
10
+ def generateMetamodel(rootPackage, out_file, modules=[])
11
+ tc = RGen::TemplateLanguage::DirectoryTemplateContainer.new(UMLClassModel, File.dirname(out_file))
12
+ tpl_path = File.dirname(__FILE__) + '/templates'
13
+ tc.load(tpl_path)
14
+ tc.expand('uml_classmodel::GenerateClassModel', File.basename(out_file), modules, :for => rootPackage)
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,71 @@
1
+ require 'rgen/name_helper'
2
+
3
+ module UMLClassModel
4
+ class UMLPackage
5
+ include RGen::NameHelper
6
+
7
+ def moduleName
8
+ firstToUpper(name)
9
+ end
10
+
11
+ def qualifiedModuleName(rootPackage)
12
+ return moduleName unless superpackage and self != rootPackage
13
+ superpackage.qualifiedModuleName(rootPackage) + "::" + moduleName
14
+ end
15
+
16
+ def sortedClasses
17
+ sortArray = classes.dup
18
+ i1 = 0
19
+ while i1 < sortArray.size-1
20
+ again = false
21
+ for i2 in i1+1..sortArray.size-1
22
+ e2 = sortArray[i2]
23
+ if sortArray[i1].superclasses.include?(e2)
24
+ sortArray.delete(e2)
25
+ sortArray.insert(i1,e2)
26
+ again = true
27
+ break
28
+ end
29
+ end
30
+ i1 += 1 unless again
31
+ end
32
+ sortArray
33
+ end
34
+ end
35
+
36
+ class UMLClass
37
+ include RGen::NameHelper
38
+ def className
39
+ firstToUpper(name)
40
+ end
41
+ def qualifiedName(rootPackage)
42
+ (package ? package.qualifiedModuleName(rootPackage) + "::" : "") + className
43
+ end
44
+ def RubySuperclass(modules)
45
+ superclasses = self.superclasses.reject {|c| modules.include?(c.name)}
46
+ raise StandardError.new("#{self.name}: Duplicate superclasses: #{superclasses}") unless superclasses.size < 2
47
+ superclasses[0]
48
+ end
49
+ end
50
+
51
+ class UMLAttribute
52
+ def RubyType
53
+ typeMap = {'float' => 'Float', 'int' => 'Integer'}
54
+ typeMap[self.getType.downcase] || 'String'
55
+ end
56
+ end
57
+
58
+ class UMLAssociationEnd
59
+ def MName
60
+ return self.clazz.name.downcase unless role
61
+ self.role
62
+ end
63
+ def one?
64
+ self.upperMult == 1 or self.upperMult.nil?
65
+ end
66
+ def many?
67
+ self.upperMult == :many
68
+ end
69
+ end
70
+
71
+ end