rrt_ruby 0.2.1-mswin32
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.
- data/lib/riva_ruby.rb +78 -0
- data/lib/rrt_ruby/rrt_component.rb +177 -0
- data/lib/rrt_ruby/rrt_deployment.rb +96 -0
- data/lib/rrt_ruby/rrt_generic.rb +229 -0
- data/lib/rrt_ruby/rrt_logical.rb +314 -0
- data/lib/rrt_ruby.rb +46 -0
- metadata +43 -0
data/lib/riva_ruby.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
#== Synopsis
|
2
|
+
# Code used over and over again
|
3
|
+
#== Author
|
4
|
+
# Vassilis Rizopoulos
|
5
|
+
#
|
6
|
+
#== Changelog
|
7
|
+
# Created: 26.09.2005
|
8
|
+
#
|
9
|
+
# Last modified: 12.10.2005 by riva
|
10
|
+
#
|
11
|
+
#== Copyright
|
12
|
+
# Copyright (c) 2005 Vassilis Rizopoulos
|
13
|
+
#
|
14
|
+
# Licensed under the same terms as Ruby.
|
15
|
+
module RivaLib
|
16
|
+
#RivaLogger was created to make Logger integration in classes easier (I'm just bored with typing).
|
17
|
+
#
|
18
|
+
#Include this module in a class and call logger_init from it's initialize method
|
19
|
+
#and you have a default logger included in the class.
|
20
|
+
#
|
21
|
+
#Example of using this module in a class hierarchy:
|
22
|
+
#
|
23
|
+
#class Test
|
24
|
+
# include RivaLogger
|
25
|
+
# def initialize init_param,logger=nil
|
26
|
+
# @init_param=init_param
|
27
|
+
# logger_init=logger
|
28
|
+
# end
|
29
|
+
# def canta
|
30
|
+
# @logger.debug("o solemio")
|
31
|
+
# end
|
32
|
+
#end
|
33
|
+
#
|
34
|
+
# m=Test.new('cucu')
|
35
|
+
# m.canta -->nothing
|
36
|
+
# logger=Logger.new(STDOUT)
|
37
|
+
# logger.level=Logger::DEBUG
|
38
|
+
# logger.datetime_format="%Y%m%d %H:%M:%S"
|
39
|
+
# t=Test.new("cucu",logger)
|
40
|
+
# t.canta --> D, [20050914 14:40:27#2136] DEBUG -- :'o sole mio'
|
41
|
+
#
|
42
|
+
#The logger parameter in the initialize method can be used to
|
43
|
+
#pass the logging context from the instantiating object, or it can be ommited and
|
44
|
+
#the attr_writer accessor can be used in it's place.
|
45
|
+
#
|
46
|
+
#This approach has the disadvantage of conflicting with classes that already have a @logger attribute
|
47
|
+
#so some caution is required.
|
48
|
+
module RivaLogger
|
49
|
+
require 'logger'
|
50
|
+
attr_reader :logger
|
51
|
+
attr_writer :logger
|
52
|
+
def logger_init logger=nil
|
53
|
+
@logger=logger
|
54
|
+
begin
|
55
|
+
@logger=Logger.new(STDOUT)
|
56
|
+
@logger.level=Logger::WARN
|
57
|
+
@logger.level=Logger::INFO if $VERBOSE
|
58
|
+
@logger.level=Logger::DEBUG if $DEBUG
|
59
|
+
@logger.datetime_format="%Y%m%d %H:%M:%S"
|
60
|
+
end unless logger
|
61
|
+
end
|
62
|
+
|
63
|
+
#This is for use on top level scripts
|
64
|
+
#It creates a logger just as I want it
|
65
|
+
def RivaLogger.setup_logger(filename=nil,verbose=false,debug=false)
|
66
|
+
if filename
|
67
|
+
logger=Logger.new(filename)
|
68
|
+
else
|
69
|
+
logger=Logger.new(STDOUT)
|
70
|
+
end
|
71
|
+
logger.level=Logger::WARN
|
72
|
+
logger.level=Logger::INFO if verbose || $VERBOSE
|
73
|
+
logger.level=Logger::DEBUG if debug || $DEBUG
|
74
|
+
logger.datetime_format="%Y%m%d %H:%M:%S"
|
75
|
+
return logger
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
#Contains the Component View corresponding elements and Finder functionality.
|
2
|
+
#See RRT_RUBY::RRTComponent
|
3
|
+
|
4
|
+
#
|
5
|
+
RRT_DIR="rrt_ruby/" unless defined?(::RRT_DIR)
|
6
|
+
require RRT_DIR+'rrt_generic'
|
7
|
+
module RRT_RUBY
|
8
|
+
#Adds functionality for accessing the Component View of
|
9
|
+
#a RoseRT model.
|
10
|
+
module RRTComponent
|
11
|
+
#Represents an RRT Component
|
12
|
+
class Component<RRTGeneric::Element
|
13
|
+
attr_reader :platform,:type,:package
|
14
|
+
def initialize element
|
15
|
+
begin
|
16
|
+
super(element)
|
17
|
+
@type=element.Type
|
18
|
+
@platform=element.Platform
|
19
|
+
@package=element.ParentComponentPackage.GetQualifiedName
|
20
|
+
rescue
|
21
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element: #{$!}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
def to_s
|
25
|
+
super()+", #{@type}/#{@platform}."
|
26
|
+
end
|
27
|
+
end
|
28
|
+
#A Library Component
|
29
|
+
class Library<Component
|
30
|
+
attr_reader :output_directory,:unit_name
|
31
|
+
|
32
|
+
def initialize element
|
33
|
+
begin
|
34
|
+
super(element)
|
35
|
+
rescue
|
36
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element: #{$!}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
def to_s
|
40
|
+
super()
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#An Executable Component
|
45
|
+
class Executable<Component
|
46
|
+
attr_reader :topcapsule, :filename
|
47
|
+
|
48
|
+
def initialize element
|
49
|
+
begin
|
50
|
+
super(element)
|
51
|
+
@topcapsule=element.FindProperty("OT::CppExec","TopCapsule").Value.sub("[event_ui\r\n\tdescription='","")
|
52
|
+
@topcapsule.sub!(/'\r\n\tcaption='Select.+\n.*/,"")
|
53
|
+
@filename=""
|
54
|
+
|
55
|
+
rescue
|
56
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element: #{$!}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
def to_s
|
60
|
+
super()+", #{@topcapsule}."
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
#~ class ExternalLibrary<Component
|
65
|
+
#~ def initialize element
|
66
|
+
#~ begin
|
67
|
+
#~ super(element)
|
68
|
+
#~ rescue
|
69
|
+
#~ raise RRTGeneric::ElementException.new(element),"error while initialising element"
|
70
|
+
#~ end
|
71
|
+
#~ end
|
72
|
+
#~ def to_s
|
73
|
+
#~ super()
|
74
|
+
#~ end
|
75
|
+
#~ end
|
76
|
+
|
77
|
+
#Adds functionality for querying component view elements.
|
78
|
+
module ComponentFinderModule
|
79
|
+
#Delivers all fully qualified component names under the defined package.
|
80
|
+
#If the parameter does not correspond to a component view package it will return an empty array
|
81
|
+
def component_names root_package
|
82
|
+
components=Array.new
|
83
|
+
#first of all find the package in the model
|
84
|
+
pkg= find_component_package(root_package,debug)
|
85
|
+
begin
|
86
|
+
comps=pkg.GetAllComponents
|
87
|
+
@logger.debug("There are #{comps.Count} components under #{pkg.GetQualifiedName}")
|
88
|
+
cnt=comps.Count
|
89
|
+
1.upto(cnt){|i|
|
90
|
+
components<<comps.GetAt(i).GetQualifiedName
|
91
|
+
}
|
92
|
+
end if pkg
|
93
|
+
return components
|
94
|
+
end
|
95
|
+
#Returns all components in the given package
|
96
|
+
def components root_package
|
97
|
+
components=Array.new
|
98
|
+
#first of all find the package in the model
|
99
|
+
pkg= find_component_package(root_package,debug)
|
100
|
+
begin
|
101
|
+
comps=pkg.GetAllComponents
|
102
|
+
@logger.debug("There are #{comps.Count} components under #{pkg.GetQualifiedName}")
|
103
|
+
cnt=comps.Count
|
104
|
+
1.upto(cnt){|i|
|
105
|
+
components<<Component.new(comps.GetAt(i))
|
106
|
+
}
|
107
|
+
end if pkg
|
108
|
+
return components
|
109
|
+
end
|
110
|
+
#Returns all executables in the given package
|
111
|
+
def executables root_package
|
112
|
+
components=Array.new
|
113
|
+
#first of all find the package in the model
|
114
|
+
pkg= find_component_package(root_package,debug)
|
115
|
+
begin
|
116
|
+
comps=pkg.GetAllComponents
|
117
|
+
@logger.debug("There are #{comps.Count} components under #{pkg.GetQualifiedName}")
|
118
|
+
cnt=comps.Count
|
119
|
+
1.upto(cnt){|i|
|
120
|
+
comp=comps.GetAt(i)
|
121
|
+
components<<Executable.new(comp) if comp.Type=~/Executable/
|
122
|
+
}
|
123
|
+
end if pkg
|
124
|
+
return components
|
125
|
+
end
|
126
|
+
#returns all libraries in the given package and it's subpackages
|
127
|
+
def libraries root_package
|
128
|
+
components=Array.new
|
129
|
+
#first of all find the package in the model
|
130
|
+
pkg= find_component_package(root_package,debug)
|
131
|
+
begin
|
132
|
+
comps=pkg.GetAllComponents
|
133
|
+
@logger.debug("There are #{comps.Count} components under #{pkg.GetQualifiedName}")
|
134
|
+
cnt=comps.Count
|
135
|
+
1.upto(cnt){|i|
|
136
|
+
comp=comps.GetAt(i)
|
137
|
+
type=comp.Type
|
138
|
+
components<<Library.new(comp) if type=~/Library/ && !(type=~/External/)
|
139
|
+
}
|
140
|
+
end if pkg
|
141
|
+
return components
|
142
|
+
end
|
143
|
+
#Returns all external libraries in the given package and it's subpackages
|
144
|
+
def external_libraries root_package
|
145
|
+
comps=components(root_package,debug)
|
146
|
+
return comps.collect{|c|
|
147
|
+
c if c.type=~/External/
|
148
|
+
}.compact
|
149
|
+
end
|
150
|
+
#This will return the first component package matching the name, nil if no component package is found.
|
151
|
+
#
|
152
|
+
#If no fully qualified name is provided, then the first match is returned
|
153
|
+
def find_component_package package_name,debug=false
|
154
|
+
#get the simple package name
|
155
|
+
splitted=package_name.split("::")
|
156
|
+
simple_name=splitted[splitted.size-1] unless splitted.size==0
|
157
|
+
#get a collection with all the packages with the same name
|
158
|
+
col=@model.FindModelElements(simple_name)
|
159
|
+
count=col.Count
|
160
|
+
@logger.debug("There are #{count} packages named #{simple_name}")
|
161
|
+
1.upto(count){|i|
|
162
|
+
obj=col.GetAt(i)
|
163
|
+
#match the first if no qualified name is given
|
164
|
+
return obj if package_name==simple_name&&obj.Name==simple_name && obj.IsClass("ComponentPackage")
|
165
|
+
#match the qualified name
|
166
|
+
return obj if obj.GetQualifiedName==package_name && obj.IsClass("ComponentPackage")
|
167
|
+
}
|
168
|
+
return nil
|
169
|
+
end
|
170
|
+
end
|
171
|
+
#This is just for compatibility with the older scripts. The RRTFinder should be used instead.
|
172
|
+
class ComponentFinder<RRTGeneric::Finder
|
173
|
+
include RRTComponent::ComponentFinderModule
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#Contains the Deployment View corresponding elements and Finder functionality.
|
2
|
+
#See RRT_RUBY::RRTDeployment
|
3
|
+
|
4
|
+
#
|
5
|
+
RRT_DIR="rrt_ruby/" unless defined?(::RRT_DIR)
|
6
|
+
require RRT_DIR+'rrt_generic'
|
7
|
+
module RRT_RUBY
|
8
|
+
#Adds functionality for accessing the Deployment View of
|
9
|
+
#a RoseRT model.
|
10
|
+
module RRT_RUBY::RRTDeployment
|
11
|
+
class Processor<RRTGeneric::Element
|
12
|
+
attr_reader :cpu,:os,:address,:server,:processes
|
13
|
+
def initialize element
|
14
|
+
begin
|
15
|
+
super(element)
|
16
|
+
@cpu=element.CPU
|
17
|
+
@os=element.OS
|
18
|
+
@address=element.Address
|
19
|
+
@server=element.ServerAddress
|
20
|
+
@processes=Array.new
|
21
|
+
extract_processes(element)
|
22
|
+
rescue
|
23
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element: #{$!}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
def to_s
|
27
|
+
return super()+", #{@os}/#{@cpu}, #{@address}, #{@processes.size} processes"
|
28
|
+
end
|
29
|
+
private
|
30
|
+
def extract_processes(element)
|
31
|
+
comps=element.ComponentInstances
|
32
|
+
cnt=comps.Count
|
33
|
+
1.upto(cnt){|i|
|
34
|
+
@processes<<Instance.new(comps.GetAt(i))
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Instance<RRTGeneric::Element
|
40
|
+
def initialize element
|
41
|
+
begin
|
42
|
+
super(element)
|
43
|
+
@component=element.Component
|
44
|
+
rescue
|
45
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element #{$!}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
def to_s
|
49
|
+
super()+", #{@component}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
#Adds functionality for querying deployment view elements.
|
53
|
+
module DeploymentFinderModule
|
54
|
+
#delivers all processors under the defined package.
|
55
|
+
#If the parameter does not correspond to a deployment view package it will return an empty array
|
56
|
+
def processors root_package,debug=false
|
57
|
+
components=Array.new
|
58
|
+
#first of all find the package in the model
|
59
|
+
pkg= find_deployment_package(root_package,debug)
|
60
|
+
begin
|
61
|
+
comps=pkg.GetAllProcessors
|
62
|
+
$stdout.puts("There are #{comps.Count} processors under #{pkg.GetQualifiedName}") if debug
|
63
|
+
cnt=comps.Count
|
64
|
+
1.upto(cnt){|i|
|
65
|
+
components<<Processor.new(comps.GetAt(i))
|
66
|
+
}
|
67
|
+
end if pkg
|
68
|
+
return components
|
69
|
+
end
|
70
|
+
#This will return the first deployment package matching the name
|
71
|
+
#nil if no deployment package is found
|
72
|
+
#if no fully qualified name is provided, then the first match is returned
|
73
|
+
def find_deployment_package package_name,debug=false
|
74
|
+
#get the simple package name
|
75
|
+
splitted=package_name.split("::")
|
76
|
+
simple_name=splitted[splitted.size-1] unless splitted.size==0
|
77
|
+
#get a collection with all the packages with the same name
|
78
|
+
col=@model.FindModelElements(simple_name)
|
79
|
+
count=col.Count
|
80
|
+
$stdout.puts "There are #{count} packages named #{simple_name}" if debug
|
81
|
+
1.upto(count){|i|
|
82
|
+
obj=col.GetAt(i)
|
83
|
+
#match the first if no qualified name is given
|
84
|
+
return obj if package_name==simple_name&&obj.Name==simple_name && obj.IsClass("DeploymentPackage")
|
85
|
+
#match the qualified name
|
86
|
+
return obj if obj.GetQualifiedName==package_name && obj.IsClass("DeploymentPackage")
|
87
|
+
}
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
#This is just for compatibility with the older scripts. The RRTFinder should be used instead.
|
92
|
+
class DeploymentFinder<RRTGeneric::Finder
|
93
|
+
include RRTDeployment::DeploymentFinderModule
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
RRT_DIR="rrt_ruby/" unless defined?(::RRT_DIR)
|
2
|
+
require RRT_DIR+'../riva_ruby'
|
3
|
+
module RRT_RUBY
|
4
|
+
#This module provides the namespace for the basic RRT RRTEI Ruby interface.
|
5
|
+
#
|
6
|
+
#It introduces the Finder class as the primary interface for accessing RRT models.
|
7
|
+
#
|
8
|
+
#The module (as well as the others - RRTLogical, RRTComponent, RRTDeployment)
|
9
|
+
#does not provide a one-to-one representation of RRTEI objects, just a convenience mapping
|
10
|
+
#for accessing the most important features of each view.
|
11
|
+
#
|
12
|
+
#We do not attempt to duplicate the interface, just make the most usual tasks easier.
|
13
|
+
module RRT_RUBY::RRTGeneric
|
14
|
+
require 'win32ole'
|
15
|
+
VERSION_MAJOR=1
|
16
|
+
VERSION_MINOR=0
|
17
|
+
OLEAPP_NAME='RoseRT.Application'
|
18
|
+
#This is the base class for all model elements. It corresponds to RRTEI::ModelElement
|
19
|
+
class Element
|
20
|
+
attr_reader :name,:qualifiedname,:stereotype,:documentation
|
21
|
+
#element is the OLE Object of a RRTEI::ModelElement or derived class
|
22
|
+
def initialize element
|
23
|
+
begin
|
24
|
+
@name=element.Name
|
25
|
+
@qualifiedname=element.GetQualifiedName
|
26
|
+
@stereotype=element.Stereotype
|
27
|
+
@documentation=element.Documentation
|
28
|
+
rescue
|
29
|
+
raise ElementException.new(element),"error while initialising element: #{$!}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
return "<<#{@stereotype}>>#{@name}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
#Finder provides an interface for accessing RRT models using OLE Automation.
|
38
|
+
#Finder represents a read-only interface to a model's content, and will remain so in future versions.
|
39
|
+
#
|
40
|
+
#It will create an OLE Instance of RRT on initialization.
|
41
|
+
#
|
42
|
+
#In order to properly release this instance Finder#stop must be called prior to exiting
|
43
|
+
#the Ruby application.
|
44
|
+
#
|
45
|
+
#Alternatively Finder#open can be used with a block.
|
46
|
+
#
|
47
|
+
#RRT under Windows XP (not tested on other versions) only allows three instances. Unfortunately, once an OLE Automation instance
|
48
|
+
#is accessed, references prevent the instances from being destroyed even after stopping a Finder.
|
49
|
+
#
|
50
|
+
#This effectively limits the number of possible Finder instances per application to three.
|
51
|
+
#
|
52
|
+
#Notice that you still need to call stop or use open with a block otherwise the RRT
|
53
|
+
#application will remain in memory after termination of the Ruby application.
|
54
|
+
class Finder
|
55
|
+
include RivaLib::RivaLogger
|
56
|
+
attr_reader :modelname, :model
|
57
|
+
#Initialize will throw an exception if the model cannot be opened.
|
58
|
+
#
|
59
|
+
#Finder uses Logger to log on STDOUT. Optionally you can pass a Logger instance
|
60
|
+
#and it will be used.
|
61
|
+
def initialize modelname="",logger=nil
|
62
|
+
@modelname=modelname
|
63
|
+
@app=WIN32OLE.new(RRTGeneric::OLEAPP_NAME)
|
64
|
+
@model=@app.OpenModel(@modelname) unless modelname.empty?
|
65
|
+
logger_init(logger)
|
66
|
+
end
|
67
|
+
#open is used in conjuction with a block.
|
68
|
+
#
|
69
|
+
#It creates a Finder instance and passes it to the block.
|
70
|
+
#At the end of the block the Finder is stopped and invalidated.
|
71
|
+
#
|
72
|
+
#You can optionally pass a Logger instance to be used by the Finder.
|
73
|
+
#
|
74
|
+
#Without a block the method is just an alias for Finder#new
|
75
|
+
def Finder.open modelname,logger=nil
|
76
|
+
begin
|
77
|
+
fndr=new(modelname,logger)
|
78
|
+
if block_given?
|
79
|
+
begin
|
80
|
+
yield fndr
|
81
|
+
ensure
|
82
|
+
fndr.stop
|
83
|
+
end
|
84
|
+
else
|
85
|
+
return fndr
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
#Instructs the Finder to load a new model into it's associated RRT instance.
|
90
|
+
#
|
91
|
+
#If modelname matches the current modelname or the Finder is invalid...well, nothing will happen.
|
92
|
+
def reload modelname
|
93
|
+
begin
|
94
|
+
@modelname=modelname
|
95
|
+
@model=@app.openmodel(@modelname)
|
96
|
+
end if @app && @app.CurrentModel.GetFileName.upcase!=modelname.upcase
|
97
|
+
end
|
98
|
+
#Stops the Finder releasing the OLE interface and invalidating this Finder instance.
|
99
|
+
#
|
100
|
+
#This method *must* be called to clean up resources unless you used Finder#start with a block.
|
101
|
+
#
|
102
|
+
#If you don't call this method you will end up with a zombie RoserRT instance and a couple of MBs less memory.
|
103
|
+
#
|
104
|
+
#After calling stop the Finder instance cannot be used again (most methods throw a FinderException).
|
105
|
+
#
|
106
|
+
#Unfortunately, there is no control on when the RRT instance is going to exit.
|
107
|
+
#
|
108
|
+
#Usually RRT instances that have been accessed will not exit until the application/script ends.
|
109
|
+
#Since RRT only allows three running instances, this means you can only reload a stopped finder twice.
|
110
|
+
def stop
|
111
|
+
@logger.debug("Stopping Finder")
|
112
|
+
@app.exit if @app
|
113
|
+
@app.ole_free()
|
114
|
+
@model=nil
|
115
|
+
@app=nil
|
116
|
+
end
|
117
|
+
#Shows the RRT UI for the associated OLE instance
|
118
|
+
#Makes the RRT UI associated with the Finder visible.
|
119
|
+
#
|
120
|
+
#Throws a FinderException if no instance exists
|
121
|
+
def show
|
122
|
+
raise FinderException.new(@modelname),"This Finder instance is invalid" unless @model
|
123
|
+
@app.visible=true
|
124
|
+
end
|
125
|
+
#Hides the RRT UI for the associated OLE instance.
|
126
|
+
#
|
127
|
+
#Throws a FinderException if no instance exists
|
128
|
+
def hide
|
129
|
+
raise FinderException.new(@modelname),"This Finder instance is invalid" unless @model
|
130
|
+
@app.visible=false
|
131
|
+
end
|
132
|
+
#returns the name of the model with which the finder is connected
|
133
|
+
#Alias for LogicalFinder#modelname
|
134
|
+
def name
|
135
|
+
return @modelname
|
136
|
+
end
|
137
|
+
def to_s
|
138
|
+
return "Active on #{@modelname}" if @model
|
139
|
+
return "Invalid for #{@modelname}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
#This is a convenience method that makes some assumptions about the use of the win32ole interface.
|
144
|
+
#
|
145
|
+
#It is here to be used with scripts that don't need the full Finder functionality or want to work directly with the RRTEI interface.
|
146
|
+
#
|
147
|
+
#It only takes a block to make sure we clean up the application object afterwards.
|
148
|
+
#This cleanup has a sideeffect: open RRT instances will be closed after the block finishes.
|
149
|
+
#
|
150
|
+
#RRT only seems to create one OLE application server (instance started with this session do not register as OLE servers).
|
151
|
+
def RRTGeneric.open_model pathname,logger=nil
|
152
|
+
#opens the model with the given pathname and returns a reference to the Win32OLE model object.
|
153
|
+
#first check the pathname
|
154
|
+
if File.exists?(pathname) then
|
155
|
+
#check if there is an open RRT instance with this model
|
156
|
+
begin
|
157
|
+
rt = WIN32OLE.connect(RRTGeneric::OLEAPP_NAME)
|
158
|
+
rescue
|
159
|
+
#no OLE Server present, create a new instance
|
160
|
+
logger.info("No OLE Server found. Creating new instance") if logger
|
161
|
+
rt=WIN32OLE.new(RRTGeneric::OLEAPP_NAME)
|
162
|
+
end
|
163
|
+
begin
|
164
|
+
# We are in Windows so filenames are case insensitive
|
165
|
+
if rt.CurrentModel.GetFileName.upcase==pathname.upcase
|
166
|
+
logger.debug("Using existing model") if logger
|
167
|
+
model = rt.CurrentModel
|
168
|
+
#it was open before, so don't close the app at the end
|
169
|
+
exit_app=false
|
170
|
+
else
|
171
|
+
logger.info("Opening model") if logger
|
172
|
+
model=rt.openmodel(pathname)
|
173
|
+
exit_app=true
|
174
|
+
end
|
175
|
+
yield model
|
176
|
+
ensure
|
177
|
+
if rt && exit_app
|
178
|
+
rt.exit
|
179
|
+
rt.ole_free()
|
180
|
+
end
|
181
|
+
end
|
182
|
+
return model
|
183
|
+
else
|
184
|
+
logger.fatal("File not found #{pathname}") if logger
|
185
|
+
end if block_given?
|
186
|
+
end
|
187
|
+
#Given a valid model (OLE object) it will return the first OLE object matching name and type.
|
188
|
+
#
|
189
|
+
#This wraps the FindModelElements method of the RRTEI API.
|
190
|
+
def RRTGeneric.find_element model,name,type
|
191
|
+
raise FinderException.new(""),"no model specified" unless model
|
192
|
+
col=model.FindModelElements(name)
|
193
|
+
count=col.Count
|
194
|
+
1.upto(count){|i|
|
195
|
+
it=col.GetAt(i)
|
196
|
+
return it if it && it.Name==name && it.IsClass(type)
|
197
|
+
}
|
198
|
+
return nil
|
199
|
+
end
|
200
|
+
|
201
|
+
#Returns the pathname for the current model if an OLE server is present, nil otherwise
|
202
|
+
def RRTGeneric.current_model
|
203
|
+
begin
|
204
|
+
rt = WIN32OLE.connect(RRTGeneric::OLEAPP_NAME)
|
205
|
+
return rt.CurrentModel.GetFileName
|
206
|
+
rescue
|
207
|
+
return nil
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
class ModelException<RuntimeError
|
212
|
+
def initialize(model)
|
213
|
+
@model=model
|
214
|
+
end
|
215
|
+
end
|
216
|
+
class ElementException<RuntimeError
|
217
|
+
def initialize element
|
218
|
+
@element=element
|
219
|
+
end
|
220
|
+
end
|
221
|
+
class FinderException<RuntimeError
|
222
|
+
attr_reader :modelname
|
223
|
+
def initialize modelname
|
224
|
+
super
|
225
|
+
@modelname=modelname
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -0,0 +1,314 @@
|
|
1
|
+
#Contains the Logical View corresponding elements and Finder functionality.
|
2
|
+
#See RRT_RUBY::RRTLogical
|
3
|
+
|
4
|
+
#
|
5
|
+
RRT_DIR="rrt_ruby/" unless defined?(::RRT_DIR)
|
6
|
+
require RRT_DIR+'rrt_generic'
|
7
|
+
module RRT_RUBY
|
8
|
+
#Adds functionality for accessing the Logical View of
|
9
|
+
#a RoseRT model.
|
10
|
+
module RRT_RUBY::RRTLogical
|
11
|
+
class LogicalPackage<RRTGeneric::Element
|
12
|
+
attr_reader :capsules,:classes,:packages,:protocols,:parent
|
13
|
+
def initialize element
|
14
|
+
begin
|
15
|
+
super(element)
|
16
|
+
@capsules=extract_capsules(element.Capsules)
|
17
|
+
@classes=extract_classes(element.Classes)
|
18
|
+
@packages=extract_packages(element.LogicalPackages)
|
19
|
+
@protocols=extract_protocols(element.Protocols)
|
20
|
+
@parent=element.ParentLogicalPackage.GetQualifiedName
|
21
|
+
end
|
22
|
+
end
|
23
|
+
def to_s
|
24
|
+
return "#{@name}, #{@packages.size} packages, #{@capsules.size} capsules, #{@classes.size} classes, #{@protocols.size} protocols"
|
25
|
+
end
|
26
|
+
private
|
27
|
+
def extract_classes col
|
28
|
+
ar=Array.new
|
29
|
+
count=col.Count
|
30
|
+
1.upto(count){|i|
|
31
|
+
ar<<RRTLogical::Class.new(col.GetAt(i))
|
32
|
+
}
|
33
|
+
return ar
|
34
|
+
end
|
35
|
+
def extract_capsules col
|
36
|
+
ar=Array.new
|
37
|
+
count=col.Count
|
38
|
+
1.upto(count){|i|
|
39
|
+
ar<<Capsule.new(col.GetAt(i))
|
40
|
+
}
|
41
|
+
return ar
|
42
|
+
end
|
43
|
+
def extract_protocols col
|
44
|
+
ar=Array.new
|
45
|
+
count=col.Count
|
46
|
+
1.upto(count){|i|
|
47
|
+
ar<<Protocol.new(col.GetAt(i))
|
48
|
+
}
|
49
|
+
return ar
|
50
|
+
end
|
51
|
+
def extract_packages col
|
52
|
+
ar=Array.new
|
53
|
+
count=col.Count
|
54
|
+
1.upto(count){|i|
|
55
|
+
ar<<LogicalPackage.new(col.GetAt(i))
|
56
|
+
}
|
57
|
+
return ar
|
58
|
+
end
|
59
|
+
end
|
60
|
+
class Capsule<RRTGeneric::Element
|
61
|
+
attr_reader :roles,:connectors,:dependencies
|
62
|
+
def initialize element
|
63
|
+
begin
|
64
|
+
super(element)
|
65
|
+
#get the roles out of the element
|
66
|
+
@roles=extract_roles(element.Structure.ClassifierRoles)
|
67
|
+
@connectors=extract_connectors(element.Structure.Connectors)
|
68
|
+
@dependencies=extract_dependencies(element.GetClassDependencies)
|
69
|
+
rescue
|
70
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element: #{$!}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_s
|
75
|
+
return "#{@name}, #{@roles.size} roles, #{@dependencies.size} dependencies"
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
#extracts information out of the OLE element to construct the list of Roles contained in the capsule
|
80
|
+
def extract_roles col
|
81
|
+
ar=Array.new
|
82
|
+
count=col.Count
|
83
|
+
1.upto(count){|i|
|
84
|
+
ar<<Role.new(col.GetAt(i))
|
85
|
+
}
|
86
|
+
return ar
|
87
|
+
end
|
88
|
+
#extracts information out of the OLE element to construct the list of Connectors contained in the capsule
|
89
|
+
def extract_connectors col
|
90
|
+
ar=Array.new
|
91
|
+
count=col.Count
|
92
|
+
1.upto(count){|i|
|
93
|
+
ar<<Connector.new(col.GetAt(i))
|
94
|
+
}
|
95
|
+
return ar
|
96
|
+
end
|
97
|
+
#extracts the classes with which this capsule has a dependency
|
98
|
+
def extract_dependencies col
|
99
|
+
ar=Array.new
|
100
|
+
count=col.Count
|
101
|
+
1.upto(count){|i|
|
102
|
+
ar<<RRTLogical::Class.new(col.GetAt(i).GetSupplierClassifier)
|
103
|
+
}
|
104
|
+
return ar
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
class Role<RRTGeneric::Element
|
110
|
+
attr_reader :class_name, :cardinality, :capsule, :parent
|
111
|
+
def initialize element
|
112
|
+
begin
|
113
|
+
super(element)
|
114
|
+
#name for the class and cardinality
|
115
|
+
@class_name=element.ClassifierName
|
116
|
+
@cardinality=element.multiplicity
|
117
|
+
#get the name of the capsule containing the role
|
118
|
+
@parent=element.ParentCollaboration.ParentClassifier.Name
|
119
|
+
#get the capsule for the role
|
120
|
+
@capsule=nil
|
121
|
+
#checking against the name of the parent ensures that we avoid endless loops
|
122
|
+
@capsule=Capsule.new(element.Classifier) if element.Classifier.IsClass("Capsule") && element.Classifier.name==@parent
|
123
|
+
rescue
|
124
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element: #{$!}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_s
|
129
|
+
return "#{@name}/#{@class_name}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
class Connector<RRTGeneric::Element
|
135
|
+
attr_reader :connects_to,:cardinality
|
136
|
+
def initialize element
|
137
|
+
begin
|
138
|
+
super(element)
|
139
|
+
@connects_to=Array.new
|
140
|
+
#this gets name of the capsule containing the port this connector connects to.
|
141
|
+
#with this configuration the Connector is only to be used as a member of a capsule (so this defines one end of the connection and the parent object defines the other end)
|
142
|
+
@connects_to<<element.PortRole1.ParentCapsuleRole.Name if element.PortRole1
|
143
|
+
@connects_to<<element.PortRole2.ParentCapsuleRole.Name if element.PortRole2
|
144
|
+
@cardinality=element.Cardinality
|
145
|
+
rescue
|
146
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element:#{$!}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def to_s
|
151
|
+
super()
|
152
|
+
end
|
153
|
+
end
|
154
|
+
class Class<RRTGeneric::Element
|
155
|
+
attr_reader :attributes
|
156
|
+
def initialize element
|
157
|
+
begin
|
158
|
+
super(element)
|
159
|
+
@attributes=extract_attributes(element)
|
160
|
+
rescue
|
161
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element: #{$!}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def to_s
|
166
|
+
super()+", #{@attributes.size} attributes"
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
#extracts the attributes of this class
|
171
|
+
def extract_attributes element
|
172
|
+
ar=Hash.new
|
173
|
+
col=element.Attributes
|
174
|
+
count=col.Count
|
175
|
+
1.upto(count){|i|
|
176
|
+
a=Attribute.new(col.GetAt(i))
|
177
|
+
ar[a.name]=a
|
178
|
+
}
|
179
|
+
return ar
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class Attribute<RRTGeneric::Element
|
184
|
+
attr_reader :init_value, :type
|
185
|
+
|
186
|
+
def initialize element
|
187
|
+
begin
|
188
|
+
super(element)
|
189
|
+
@init_value=element.InitValue
|
190
|
+
@type=element.Type
|
191
|
+
rescue
|
192
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element: #{$!}"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def to_s
|
197
|
+
return "#{@name}=#{@init_value}/#{@type}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
class Protocol<RRTGeneric::Element
|
201
|
+
def initialize element
|
202
|
+
begin
|
203
|
+
super(element)
|
204
|
+
rescue
|
205
|
+
raise RRTGeneric::ElementException.new(element),"error while initialising element: #{$!}"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def to_s
|
210
|
+
super()
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
#Adds functionlaity for querying component view elements.
|
215
|
+
module LogicalFinderModule
|
216
|
+
LOGICAL_PACKAGE='LogicalPackage'
|
217
|
+
#delivers all fully qualified capsule names under the defined package.
|
218
|
+
#If the parameter does not correspond to a logical view package it will return an empty array
|
219
|
+
#It will not recurse.
|
220
|
+
def capsule_names root_package,debug=false
|
221
|
+
raise RRTGeneric::FinderException.new(@modelname),"This Finder instance is invalid" unless @model
|
222
|
+
capsules=Array.new
|
223
|
+
#first of all find the package in the model
|
224
|
+
pkg= find_logical_package(root_package,debug)
|
225
|
+
begin
|
226
|
+
caps=pkg.capsules
|
227
|
+
@logger.debug("There are #{caps.size} capsules under #{pkg.qualifiedname}")
|
228
|
+
caps.each{|i|
|
229
|
+
capsules<<caps.qualifiedname
|
230
|
+
}
|
231
|
+
end if pkg
|
232
|
+
return capsules
|
233
|
+
end
|
234
|
+
#delivers all fully qualified package names under the defined package.
|
235
|
+
#If the parameter does not correspond to a logical view package it will return an empty array
|
236
|
+
#It will not recurse.
|
237
|
+
def package_names root_package,debug=false
|
238
|
+
raise RRTGeneric::FinderException.new(@modelname),"This Finder instance is invalid" unless @model
|
239
|
+
packages=Array.new
|
240
|
+
#first of all find the package in the model
|
241
|
+
pkg= find_logical_package(root_package,debug)
|
242
|
+
begin
|
243
|
+
caps=pkg.LogicalPackages
|
244
|
+
@logger.debug("There are #{caps.Count} packages under #{pkg.GetQualifiedName}")
|
245
|
+
cnt=caps.Count
|
246
|
+
1.upto(cnt){|i|
|
247
|
+
packages<<caps.GetAt(i).GetQualifiedName
|
248
|
+
}
|
249
|
+
end if pkg
|
250
|
+
return packages
|
251
|
+
end
|
252
|
+
|
253
|
+
#This will return the first logical view package matching the name or
|
254
|
+
#nil if no package is found
|
255
|
+
#if no fully qualified name is provided, then the first match is returned
|
256
|
+
def find_logical_package package_name,debug=false
|
257
|
+
ret=nil
|
258
|
+
raise RRTGeneric::FinderException.new(@modelname),"This Finder instance is invalid" unless @model
|
259
|
+
#get the simple package name
|
260
|
+
splitted=package_name.split("::")
|
261
|
+
simple_name=splitted[splitted.size-1] unless splitted.size==0
|
262
|
+
#get a collection with all the packages with the same name
|
263
|
+
col=@model.FindModelElements(simple_name)
|
264
|
+
count=col.Count
|
265
|
+
@logger.debug("There are #{count} packages named #{simple_name}")
|
266
|
+
1.upto(count){|i|
|
267
|
+
obj=col.GetAt(i)
|
268
|
+
#match the first if no qualified name is given
|
269
|
+
ret=LogicalPackage.new(obj) if obj&&package_name==simple_name&&obj.Name==simple_name && obj.IsClass(LOGICAL_PACKAGE)
|
270
|
+
#match the qualified name
|
271
|
+
ret=LogicalPackage.new(obj) if obj&&obj.GetQualifiedName==package_name && obj.IsClass(LOGICAL_PACKAGE)
|
272
|
+
}
|
273
|
+
col=nil
|
274
|
+
count=0
|
275
|
+
return ret
|
276
|
+
end
|
277
|
+
|
278
|
+
def find_capsule capsule_name
|
279
|
+
raise RRTGeneric::FinderException.new(@modelname),"This Finder instance is invalid" unless @model
|
280
|
+
#get the simple capsule name
|
281
|
+
splitted=capsule_name.split("::")
|
282
|
+
simple_name=splitted[splitted.size-1] unless splitted.size==0
|
283
|
+
#find it
|
284
|
+
col=@model.FindModelElements(simple_name)
|
285
|
+
count=col.Count
|
286
|
+
1.upto(count){|i|
|
287
|
+
it=col.GetAt(i)
|
288
|
+
#match the first if no qualified name is given
|
289
|
+
return Capsule.new(it) if it &&capsule_name==simple_name&&it.Name==capsule_name && it.IsClass("Capsule")
|
290
|
+
#match the qualified name
|
291
|
+
return Capsule.new(it) if it&&it.GetQualifiedName==capsule_name&& it.IsClass("Capsule")
|
292
|
+
}
|
293
|
+
@logger.debug("Capsule #{capsule_name} not found in #{@modelname}")
|
294
|
+
return nil
|
295
|
+
end
|
296
|
+
#returns the RRTLogical::Class instance of the first class with the provided name.
|
297
|
+
#nil if nothing is found
|
298
|
+
def find_class name
|
299
|
+
raise RRTGeneric::FinderException.new(@modelname) unless @model
|
300
|
+
col=@model.FindModelElements(name)
|
301
|
+
count=col.Count
|
302
|
+
1.upto(count){|i|
|
303
|
+
it=col.GetAt(i)
|
304
|
+
return Class.new(it) if it && it.Name==name && it.IsClass("Class")
|
305
|
+
}
|
306
|
+
return nil
|
307
|
+
end
|
308
|
+
end
|
309
|
+
#This is just for compatibility with the older scripts. The RRTFinder should be used instead.
|
310
|
+
class LogicalFinder<RRTGeneric::Finder
|
311
|
+
include RRTLogical::LogicalFinderModule
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
data/lib/rrt_ruby.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#rrt_ruby is a library that provides access to Rational Rose RealTime models through RRTEI (The Rose Real Time Extensibility Interface).
|
2
|
+
#In order to use it, you need a valid RoseRT license.
|
3
|
+
#
|
4
|
+
#For more information look at RRT_RUBY
|
5
|
+
|
6
|
+
#
|
7
|
+
RRT_DIR="rrt_ruby/" unless defined?(::RRT_DIR)
|
8
|
+
require RRT_DIR+'rrt_logical'
|
9
|
+
require RRT_DIR+'rrt_deployment'
|
10
|
+
require RRT_DIR+'rrt_component'
|
11
|
+
#== Synopsis
|
12
|
+
#The RRT_RUBY module provides the namespace for the rrt_ruby library.
|
13
|
+
#
|
14
|
+
#The library defines a set of objects that correspond to model elements and the RRTFinder class that provides a way of querying a model.
|
15
|
+
#
|
16
|
+
#
|
17
|
+
#== Usage
|
18
|
+
#The following code will return a LogicalPackage instance representing the requested package containing all capsules, classes and packages thereof.
|
19
|
+
##The backslashes are vital - '/' won't work because we are making an OLE call and RoseRT doesn't understand paths with '/'.
|
20
|
+
# RRTFinder.open("path\\name\\to\\model.rtmdl"){|finder|
|
21
|
+
# finder.find_logical_package("Package")
|
22
|
+
# }
|
23
|
+
#
|
24
|
+
#== Author
|
25
|
+
# Vassilis Rizopoulos
|
26
|
+
#
|
27
|
+
#== Changelog
|
28
|
+
# Created: 28.09.2005
|
29
|
+
#
|
30
|
+
# Last modified: 28.09.2005 by damphyr
|
31
|
+
#
|
32
|
+
#== Copyright
|
33
|
+
# Copyright (c) 2005 Vassilis Rizopoulos
|
34
|
+
#
|
35
|
+
# Licensed under the same terms as Ruby.
|
36
|
+
public
|
37
|
+
module RRT_RUBY
|
38
|
+
VERSION_MAJOR='0'
|
39
|
+
VERSION_MINOR='2'
|
40
|
+
#RRTFinder aggregates the RRTLogical, RRTComponent and RRTDeployment modules to provide access to all views of a RoseRT model (ok, ok, RRTUseCase is missing)
|
41
|
+
class RRTFinder<RRTGeneric::Finder
|
42
|
+
include RRTLogical::LogicalFinderModule
|
43
|
+
include RRTComponent::ComponentFinderModule
|
44
|
+
include RRTDeployment::DeploymentFinderModule
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.3
|
3
|
+
specification_version: 1
|
4
|
+
name: rrt_ruby
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.2.1
|
7
|
+
date: 2005-10-13
|
8
|
+
summary: rrt_ruby is a Ruby library providing access to Rose RealTime models through RRTEI
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: riva@braveworld.net
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: mswin32
|
27
|
+
authors:
|
28
|
+
- Vassilis Rizopoulos
|
29
|
+
files:
|
30
|
+
- lib/riva_ruby.rb
|
31
|
+
- lib/rrt_ruby.rb
|
32
|
+
- lib/rrt_ruby/rrt_component.rb
|
33
|
+
- lib/rrt_ruby/rrt_deployment.rb
|
34
|
+
- lib/rrt_ruby/rrt_generic.rb
|
35
|
+
- lib/rrt_ruby/rrt_logical.rb
|
36
|
+
test_files: []
|
37
|
+
rdoc_options: []
|
38
|
+
extra_rdoc_files: []
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
requirements:
|
42
|
+
- A Rational Rose Real Time installation with version 2002.05.20 or later on Windows
|
43
|
+
dependencies: []
|