rgen 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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