rrt_ruby 0.2.1-mswin32 → 0.3.0-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/rrt_ruby/classes.rb +879 -0
- data/lib/rrt_ruby/finder.rb +264 -0
- data/lib/rrt_ruby/writer.rb +166 -0
- data/lib/rrt_ruby.rb +161 -18
- metadata +5 -6
- data/lib/rrt_ruby/rrt_component.rb +0 -177
- data/lib/rrt_ruby/rrt_deployment.rb +0 -96
- data/lib/rrt_ruby/rrt_generic.rb +0 -229
- data/lib/rrt_ruby/rrt_logical.rb +0 -314
@@ -0,0 +1,264 @@
|
|
1
|
+
RRT_DIR="rrt_ruby/" unless defined?(::RRT_DIR)
|
2
|
+
require RRT_DIR+'classes'
|
3
|
+
module RRT_RUBY
|
4
|
+
#This module defines the 'read' operations for a model.
|
5
|
+
#
|
6
|
+
#== Usage
|
7
|
+
#Using the Finder#find_logical_package, Finder#find_class, Finder#find_capsule (and the analogous component and deployment view calls) generates several OLE calls and possibly dulicate information.
|
8
|
+
#
|
9
|
+
#An example of creating duplicate information is using Finder#find_logical_package to access logical package A and then logical package B contained in A.
|
10
|
+
#
|
11
|
+
#The first call (accessing A) will return the LogicalPackage instance of A that already contains a LogicalPackage instance with the information of B.
|
12
|
+
#
|
13
|
+
#The second call will create a separate LogicalPackage instance with the information of B.
|
14
|
+
#
|
15
|
+
#It is recommended to always look for the top most package and then perform all operations using one of the LogicalPackage, ComponentPackage, DeploymentPackage classes.
|
16
|
+
#
|
17
|
+
#Moreover, the Finder#root_logical_package method caches the retrieved LogicalPackage instance, so subsequent calls do not generate further OLE calls.
|
18
|
+
#
|
19
|
+
#Finder#root_component_package, Finder#root_deployment_package etc. also do this for their respective Package instances.
|
20
|
+
module Finder
|
21
|
+
#Errors accessing the OLE Server are reported with this class
|
22
|
+
class FinderException<RuntimeError
|
23
|
+
attr_reader :modelname
|
24
|
+
def initialize modelname
|
25
|
+
super
|
26
|
+
@modelname=modelname
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
TYPE_CLASS='Class'#OLE element type
|
31
|
+
TYPE_CAPSULE='Capsule'#OLE element type
|
32
|
+
TYPE_PROTOCOL='Protocol'#OLE element type
|
33
|
+
TYPE_LOGICAL_PACKAGE='LogicalPackage'#OLE element type
|
34
|
+
TYPE_DEPLOYMENT_PACKAGE='DeploymentPackage'#OLE element type
|
35
|
+
TYPE_COMPONENT_PACKAGE='ComponentPackage'#OLE element type
|
36
|
+
|
37
|
+
#Returns the first OLE element with the given name, optionally if it's of the given type.
|
38
|
+
#
|
39
|
+
#Use the TYPE_ constants to define the element types
|
40
|
+
def ole_element name,type=nil
|
41
|
+
check
|
42
|
+
#get the simple name
|
43
|
+
splitted=name.split("::")
|
44
|
+
simple_name=splitted[splitted.size-1] unless splitted.size==0
|
45
|
+
#find it
|
46
|
+
col=@model.FindModelElements(simple_name)
|
47
|
+
count=col.Count
|
48
|
+
1.upto(count){|i|
|
49
|
+
it=col.GetAt(i)
|
50
|
+
#match the first if no qualified name is given
|
51
|
+
if type
|
52
|
+
return it if it.IsClass(type)
|
53
|
+
else
|
54
|
+
return it
|
55
|
+
end if it&&name==simple_name&&it.Name==name
|
56
|
+
#match the qualified name
|
57
|
+
if type
|
58
|
+
return it if it.IsClass(type)
|
59
|
+
else
|
60
|
+
return it
|
61
|
+
end if it&&it.GetQualifiedName==name
|
62
|
+
}
|
63
|
+
@logger.warn("Element #{name} not found in #{@modelname}")
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
#This will return the logical view package matching the name or
|
67
|
+
#nil if no package is found.
|
68
|
+
#
|
69
|
+
#If no fully qualified name is provided, then the first match is returned.
|
70
|
+
#
|
71
|
+
#Note that a package contains other packages and capsules and classes and this information is all read when calling this method
|
72
|
+
#so looking for a package high in the hierarchy can yield a structure containing most or all of the logical view of the model.
|
73
|
+
#
|
74
|
+
#Specifying "" or "LogicalView" as package_name will return the entire Logical View contents. See also LogicalFinder#root_package
|
75
|
+
def find_logical_package package_name
|
76
|
+
check
|
77
|
+
return root_logical_package if package_name=="" || package_name=="LogicalView"
|
78
|
+
el=ole_element(package_name,TYPE_LOGICAL_PACKAGE)
|
79
|
+
return LogicalPackage.new(el) if el
|
80
|
+
@logger.debug("Package #{package_name} not found in #{@modelname}") unless el
|
81
|
+
return nil
|
82
|
+
end
|
83
|
+
#Returns the first Capsule that matches the given name, nil if no match is made.
|
84
|
+
def find_capsule name
|
85
|
+
check
|
86
|
+
el=ole_element(name,TYPE_CAPSULE)
|
87
|
+
return Capsule.new(el) if el
|
88
|
+
@logger.debug("Capsule #{name} not found in #{@modelname}")
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
#Returns the RRT_RUBY::Class instance of the first class with the provided name
|
92
|
+
#nil if nothing is found.
|
93
|
+
def find_class name
|
94
|
+
check
|
95
|
+
el=ole_element(name,TYPE_CLASS)
|
96
|
+
return RRT_RUBY::Class.new(el) if el
|
97
|
+
@logger.debug("Class #{name} not found in #{@modelname}")
|
98
|
+
return nil
|
99
|
+
end
|
100
|
+
|
101
|
+
#Returns the LogicalPackage instance for Logical View. Essentially this instance contains the complete logical view contents
|
102
|
+
def root_logical_package
|
103
|
+
check
|
104
|
+
@logical_view=LogicalPackage.new(@model.RootLogicalPackage) unless @logical_view
|
105
|
+
return @logical_view
|
106
|
+
end
|
107
|
+
|
108
|
+
#Returns the ComponentPackage instance for Component View. Essentially this instance contains the complete component view contents
|
109
|
+
def root_component_package
|
110
|
+
check
|
111
|
+
@component_view=ComponentPackage.new(@model.RootComponentPackage) unless @component_view
|
112
|
+
return @component_view
|
113
|
+
end
|
114
|
+
#Returns the DeploymentPackage instance for Deployment View. Essentially this instance contains the complete deployment view contents
|
115
|
+
def root_deployment_package
|
116
|
+
check
|
117
|
+
@deployment_view=DeploymentPackage.new(@model.RootDeploymentPackage) unless @deployment_view
|
118
|
+
return @deployment_view
|
119
|
+
end
|
120
|
+
|
121
|
+
#Delivers all fully qualified component names under the defined package.
|
122
|
+
#If the parameter does not correspond to a component view package it will return an empty array
|
123
|
+
def component_names root_package
|
124
|
+
check
|
125
|
+
components=Array.new
|
126
|
+
#first of all find the package in the model
|
127
|
+
pkg= find_component_package(root_package)
|
128
|
+
begin
|
129
|
+
comps=pkg.GetAllComponents
|
130
|
+
@logger.debug("There are #{comps.Count} components under #{pkg.GetQualifiedName}")
|
131
|
+
cnt=comps.Count
|
132
|
+
1.upto(cnt){|i|
|
133
|
+
components<<comps.GetAt(i).GetQualifiedName
|
134
|
+
}
|
135
|
+
end if pkg
|
136
|
+
return components
|
137
|
+
end
|
138
|
+
#Returns all components in the given package
|
139
|
+
def components root_package
|
140
|
+
check
|
141
|
+
components=Array.new
|
142
|
+
#first of all find the package in the model
|
143
|
+
pkg= find_component_package(root_package)
|
144
|
+
begin
|
145
|
+
comps=pkg.GetAllComponents
|
146
|
+
@logger.debug("There are #{comps.Count} components under #{pkg.GetQualifiedName}")
|
147
|
+
cnt=comps.Count
|
148
|
+
1.upto(cnt){|i|
|
149
|
+
components<<Component.new(comps.GetAt(i))
|
150
|
+
}
|
151
|
+
end if pkg
|
152
|
+
return components
|
153
|
+
end
|
154
|
+
#Returns all executables in the given package
|
155
|
+
def executables root_package
|
156
|
+
check
|
157
|
+
components=Array.new
|
158
|
+
#first of all find the package in the model
|
159
|
+
pkg= find_component_package(root_package)
|
160
|
+
begin
|
161
|
+
comps=pkg.GetAllComponents
|
162
|
+
@logger.debug("There are #{comps.Count} components under #{pkg.GetQualifiedName}")
|
163
|
+
cnt=comps.Count
|
164
|
+
1.upto(cnt){|i|
|
165
|
+
comp=comps.GetAt(i)
|
166
|
+
components<<Executable.new(comp) if comp.Type=~/Executable/
|
167
|
+
}
|
168
|
+
end if pkg
|
169
|
+
return components
|
170
|
+
end
|
171
|
+
#returns all libraries in the given package and it's subpackages
|
172
|
+
def libraries root_package
|
173
|
+
check
|
174
|
+
components=Array.new
|
175
|
+
#first of all find the package in the model
|
176
|
+
pkg= find_component_package(root_package)
|
177
|
+
begin
|
178
|
+
comps=pkg.GetAllComponents
|
179
|
+
@logger.debug("There are #{comps.Count} components under #{pkg.GetQualifiedName}")
|
180
|
+
cnt=comps.Count
|
181
|
+
1.upto(cnt){|i|
|
182
|
+
comp=comps.GetAt(i)
|
183
|
+
type=comp.Type
|
184
|
+
components<<Library.new(comp) if type=~/Library/ && !(type=~/External/)
|
185
|
+
}
|
186
|
+
end if pkg
|
187
|
+
return components
|
188
|
+
end
|
189
|
+
#Returns all external libraries in the given package and it's subpackages
|
190
|
+
def external_libraries root_package
|
191
|
+
check
|
192
|
+
comps=components(root_package)
|
193
|
+
return comps.collect{|c|
|
194
|
+
c if c.type=~/External/
|
195
|
+
}.compact
|
196
|
+
end
|
197
|
+
#This will return the first component package matching the name, nil if no component package is found.
|
198
|
+
#
|
199
|
+
#If no fully qualified name is provided, then the first match is returned
|
200
|
+
def find_component_package package_name=false
|
201
|
+
check
|
202
|
+
#get the simple package name
|
203
|
+
splitted=package_name.split("::")
|
204
|
+
simple_name=splitted[splitted.size-1] unless splitted.size==0
|
205
|
+
#get a collection with all the packages with the same name
|
206
|
+
col=@model.FindModelElements(simple_name)
|
207
|
+
count=col.Count
|
208
|
+
@logger.debug("There are #{count} packages named #{simple_name}")
|
209
|
+
1.upto(count){|i|
|
210
|
+
obj=col.GetAt(i)
|
211
|
+
#match the first if no qualified name is given
|
212
|
+
return obj if package_name==simple_name&&obj.Name==simple_name && obj.IsClass("ComponentPackage")
|
213
|
+
#match the qualified name
|
214
|
+
return obj if obj.GetQualifiedName==package_name && obj.IsClass("ComponentPackage")
|
215
|
+
}
|
216
|
+
return nil
|
217
|
+
end
|
218
|
+
#delivers all processors under the defined package.
|
219
|
+
#If the parameter does not correspond to a deployment view package it will return an empty array
|
220
|
+
def processors root_package
|
221
|
+
check
|
222
|
+
components=Array.new
|
223
|
+
#first of all find the package in the model
|
224
|
+
pkg= find_deployment_package(root_package)
|
225
|
+
begin
|
226
|
+
comps=pkg.GetAllProcessors
|
227
|
+
$stdout.puts("There are #{comps.Count} processors under #{pkg.GetQualifiedName}") if debug
|
228
|
+
cnt=comps.Count
|
229
|
+
1.upto(cnt){|i|
|
230
|
+
components<<Processor.new(comps.GetAt(i))
|
231
|
+
}
|
232
|
+
end if pkg
|
233
|
+
return components
|
234
|
+
end
|
235
|
+
#This will return the first deployment package matching the name
|
236
|
+
#nil if no deployment package is found
|
237
|
+
#if no fully qualified name is provided, then the first match is returned
|
238
|
+
def find_deployment_package package_name
|
239
|
+
check
|
240
|
+
#get the simple package name
|
241
|
+
splitted=package_name.split("::")
|
242
|
+
simple_name=splitted[splitted.size-1] unless splitted.size==0
|
243
|
+
#get a collection with all the packages with the same name
|
244
|
+
col=@model.FindModelElements(simple_name)
|
245
|
+
count=col.Count
|
246
|
+
$stdout.puts "There are #{count} packages named #{simple_name}" if debug
|
247
|
+
1.upto(count){|i|
|
248
|
+
obj=col.GetAt(i)
|
249
|
+
#match the first if no qualified name is given
|
250
|
+
return obj if package_name==simple_name&&obj.Name==simple_name && obj.IsClass("DeploymentPackage")
|
251
|
+
#match the qualified name
|
252
|
+
return obj if obj.GetQualifiedName==package_name && obj.IsClass("DeploymentPackage")
|
253
|
+
}
|
254
|
+
return nil
|
255
|
+
end
|
256
|
+
private
|
257
|
+
#Checks to see if the Finder instance is valid
|
258
|
+
def check
|
259
|
+
raise FinderException.new(@modelname),"This Finder instance is invalid" unless @app
|
260
|
+
raise FinderException.new(@modelname),"Model not loaded" unless @model
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
RRT_DIR="rrt_ruby/" unless defined?(::RRT_DIR)
|
2
|
+
require RRT_DIR+'finder'
|
3
|
+
module RRT_RUBY
|
4
|
+
#This module defines the interface for write operations on a model.
|
5
|
+
#
|
6
|
+
#== Usage
|
7
|
+
#Due to the fact that the OLE interface throws several exceptions
|
8
|
+
#when saving control units (when a control unit has changed in the filesystem, or when a control unit is contained in the unit that gets saved etc.)
|
9
|
+
#and in gross violation of all things OO, RRTFinder#show is used to display the prompts to the user in order to avoid the exceptions.
|
10
|
+
#
|
11
|
+
#This is going to change, but at the moment the Writer module cannot be used to fully automate generation of models with multiple control units.
|
12
|
+
#
|
13
|
+
#Additionally at the moment, all _add_ operations fail miserably when the target package already exists
|
14
|
+
module Writer
|
15
|
+
include Finder
|
16
|
+
#Adds _package_ (a LogicalPackage instance) to the model.
|
17
|
+
#
|
18
|
+
#Throws a ModelException when something goes wrong.
|
19
|
+
#
|
20
|
+
#Things that can go wrong:
|
21
|
+
#
|
22
|
+
#* The parent package for _package_ does not exist
|
23
|
+
#* The parent package for _package_ is not writeable
|
24
|
+
def add_logical_package package,save=true
|
25
|
+
@logger.debug("Adding #{package.to_s}")
|
26
|
+
#if no parent it goes directly to logical view
|
27
|
+
if package.parent.empty?
|
28
|
+
host=@model.RootLogicalPackage
|
29
|
+
else
|
30
|
+
#find if the parent exists
|
31
|
+
host=ole_element(package.parent,TYPE_LOGICAL_PACKAGE)
|
32
|
+
end
|
33
|
+
if host
|
34
|
+
if host.IsModifiable
|
35
|
+
#add the package
|
36
|
+
added_package=host.AddLogicalPackage(package.name)
|
37
|
+
added_package.stereotype=package.stereotype
|
38
|
+
#add all the classes
|
39
|
+
package.classes.each{|c|
|
40
|
+
add_class(c,added_package)
|
41
|
+
}
|
42
|
+
#add all the contained packages
|
43
|
+
package.packages.each{|p|
|
44
|
+
add_logical_package(p,false)
|
45
|
+
}
|
46
|
+
#save if wanted
|
47
|
+
begin
|
48
|
+
update_relations(package)
|
49
|
+
#show so that no errors are generated when dialogs pop up
|
50
|
+
self.show
|
51
|
+
#save, hide and invalidated the view cache
|
52
|
+
unit=host.GetContainingControlledElement
|
53
|
+
raise ModelException,"Could not save#{unit.name}" unless unit.Save
|
54
|
+
self.hide
|
55
|
+
@logical_view=nil
|
56
|
+
end if save
|
57
|
+
else
|
58
|
+
raise ModelException,"#{host.name} is not writable"
|
59
|
+
end
|
60
|
+
else
|
61
|
+
raise ModelException,"#{package.parent} does not exist in the model"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#Removes a LogicalPackage from the model.
|
66
|
+
#
|
67
|
+
#Throws a ModelException when something goes wrong.
|
68
|
+
#Things that can go wrong:
|
69
|
+
#
|
70
|
+
#* The parent package for _package_ does not exist
|
71
|
+
#* _package_ does not exist
|
72
|
+
#* The parent package for _package_ is not writeable
|
73
|
+
def remove_logical_package package
|
74
|
+
@logger.debug("Removing #{package.to_s}")
|
75
|
+
#if no parent it goes directly to logical view
|
76
|
+
if package.parent.empty?
|
77
|
+
host=@model.RootLogicalPackage
|
78
|
+
@logger.debug("...from the root logical package")
|
79
|
+
else
|
80
|
+
#find if the parent exists
|
81
|
+
host=ole_element(package.parent,TYPE_LOGICAL_PACKAGE)
|
82
|
+
end
|
83
|
+
if host
|
84
|
+
if host.IsModifiable
|
85
|
+
pkg=ole_element(package.qualified_name,TYPE_LOGICAL_PACKAGE)
|
86
|
+
if pkg
|
87
|
+
self.show
|
88
|
+
#delete the package
|
89
|
+
host.DeleteLogicalPackage(pkg)
|
90
|
+
unit=host.GetContainingControlledElement
|
91
|
+
raise ModelException,"Could not save#{unit.name}" unless unit.Save
|
92
|
+
self.hide
|
93
|
+
@logical_view=nil
|
94
|
+
else
|
95
|
+
@logger.info("#{package.name} does not exist in the model")
|
96
|
+
end
|
97
|
+
else
|
98
|
+
raise ModelException,"#{host.name} is not writable"
|
99
|
+
end
|
100
|
+
else
|
101
|
+
raise ModelException,"#{package.parent} does not exist in the model"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
#Checks if an OLE element with the given name can be written to/is modifiable
|
106
|
+
#
|
107
|
+
#Raises a ModelException if no element is found
|
108
|
+
def writeable? name
|
109
|
+
el=ole_element(name)
|
110
|
+
if el
|
111
|
+
return el.IsModifiable
|
112
|
+
else
|
113
|
+
raise ModelException,"#{name} does not exist in the model"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
#Adds _c_ to the OLE _package_element_
|
119
|
+
def add_class c,package_element
|
120
|
+
added=package_element.AddClass(c.name)
|
121
|
+
added.stereotype=c.stereotype
|
122
|
+
end
|
123
|
+
#Adds _c_ to the OLE _package_element_
|
124
|
+
def add_capsule c,package_element
|
125
|
+
added=package_element.AddCapsule(c.name)
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
#Updates all elements contained in OLE _package_
|
130
|
+
#with the proper relations
|
131
|
+
def update_relations package
|
132
|
+
package.all_classes.each{|c|
|
133
|
+
add_relations_to_element(c)
|
134
|
+
}
|
135
|
+
package.all_protocols.each{|c|
|
136
|
+
add_relations_to_element(c)
|
137
|
+
}
|
138
|
+
package.all_capsules.each{|c|
|
139
|
+
add_relations_to_element(c)
|
140
|
+
}
|
141
|
+
end
|
142
|
+
#Finds the OLE element corresponding to _c_ and creates the relations
|
143
|
+
#using the Relation instances of _c_
|
144
|
+
def add_relations_to_element c
|
145
|
+
el=ole_element(c.qualified_name)
|
146
|
+
if el
|
147
|
+
c.relations.each{|r|
|
148
|
+
begin
|
149
|
+
case r.relation_type
|
150
|
+
when Relation::CLASS
|
151
|
+
el.AddClassDependency("",r.supplier)
|
152
|
+
when Relation::COMPONENT
|
153
|
+
when Relation::PACKAGE
|
154
|
+
when Relation::GENERALIZATION
|
155
|
+
when Relation::REALIZE
|
156
|
+
end
|
157
|
+
rescue
|
158
|
+
@logger.warn("Could not add dependency: #{$!}")
|
159
|
+
end
|
160
|
+
}
|
161
|
+
else
|
162
|
+
@logger.warn("Element #{c.qualified_name} not found")
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
data/lib/rrt_ruby.rb
CHANGED
@@ -1,25 +1,39 @@
|
|
1
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.
|
2
|
+
#In order to use it, you need a valid RoseRT license (and only because you can'T start RoseRT otherwise).
|
3
3
|
#
|
4
4
|
#For more information look at RRT_RUBY
|
5
5
|
|
6
6
|
#
|
7
7
|
RRT_DIR="rrt_ruby/" unless defined?(::RRT_DIR)
|
8
|
-
require RRT_DIR+'
|
9
|
-
require RRT_DIR+'
|
10
|
-
require RRT_DIR+'
|
8
|
+
require RRT_DIR+'finder'
|
9
|
+
require RRT_DIR+'writer'
|
10
|
+
require RRT_DIR+'classes'
|
11
|
+
|
11
12
|
#== Synopsis
|
12
13
|
#The RRT_RUBY module provides the namespace for the rrt_ruby library.
|
13
14
|
#
|
14
|
-
#The library defines a set of objects that correspond to model elements
|
15
|
-
#
|
15
|
+
#The library defines a set of objects that correspond to model elements, the RRTFinder class as a read-only interface for the model and the RRTAccessor class
|
16
|
+
#as a read-write interface for the model.
|
16
17
|
#
|
17
18
|
#== Usage
|
18
|
-
#
|
19
|
-
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
19
|
+
#Since version 0.3 rrt_ruby offers a package based way of working with RRT models:
|
20
|
+
#
|
21
|
+
#UseCasePackage for accessing use case view elements
|
22
|
+
#
|
23
|
+
#LogicalPackage for accessing logical view elements
|
24
|
+
#
|
25
|
+
#ComponentPackage for accessing component view elements
|
26
|
+
#
|
27
|
+
#DeploymentPackage for accessing deployment view element
|
28
|
+
#
|
29
|
+
#The top most element of every view is the root package for every view, which means that Finder#root_logical_package will return a LogicalPackage instance containing the complete logical view.
|
30
|
+
#
|
31
|
+
#Finder#root_component_package will return a ComponentPackage instance with the complete component view and so on.
|
32
|
+
#
|
33
|
+
#Once a package element is extracted into the corresponding Package instance, the contents can be searched/altered without resorting to OLE calls.
|
34
|
+
#
|
35
|
+
#This provides us with a significant performance advantage.
|
36
|
+
#
|
23
37
|
#
|
24
38
|
#== Author
|
25
39
|
# Vassilis Rizopoulos
|
@@ -27,7 +41,7 @@ require RRT_DIR+'rrt_component'
|
|
27
41
|
#== Changelog
|
28
42
|
# Created: 28.09.2005
|
29
43
|
#
|
30
|
-
# Last modified:
|
44
|
+
# Last modified: 19.10.2005 by riva
|
31
45
|
#
|
32
46
|
#== Copyright
|
33
47
|
# Copyright (c) 2005 Vassilis Rizopoulos
|
@@ -36,11 +50,140 @@ require RRT_DIR+'rrt_component'
|
|
36
50
|
public
|
37
51
|
module RRT_RUBY
|
38
52
|
VERSION_MAJOR='0'
|
39
|
-
VERSION_MINOR='
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
53
|
+
VERSION_MINOR='3'
|
54
|
+
require 'win32ole'
|
55
|
+
require 'riva_ruby'
|
56
|
+
OLEAPP_NAME='RoseRT.Application'
|
57
|
+
|
58
|
+
#RRTFinder provides the primary interface for read-only access of RRT models using OLE Automation.
|
59
|
+
#
|
60
|
+
#It will create an OLE instance of RRT on initialization.
|
61
|
+
#
|
62
|
+
#In order to properly release this instance RRTFinder#stop must be called prior to exiting
|
63
|
+
#the Ruby application.
|
64
|
+
#
|
65
|
+
#Alternatively RRTFinder#open can be used with a block.
|
66
|
+
#
|
67
|
+
#RRT under Windows XP (not tested on other versions) only allows three instances. Unfortunately, once an OLE Automation instance
|
68
|
+
#is accessed, references prevent the instances from being destroyed even after stopping RRTFinder.
|
69
|
+
#
|
70
|
+
#This effectively limits the number of possible RRTFinder instances per application to three.
|
71
|
+
#
|
72
|
+
#Notice that you still need to call stop or use open with a block otherwise the RRT
|
73
|
+
#application will remain in memory after termination of the Ruby application.
|
74
|
+
#
|
75
|
+
#See the Finder module for a description of the actual read interface.
|
76
|
+
class RRTFinder
|
77
|
+
include RivaLib::RivaLogger
|
78
|
+
include Finder
|
79
|
+
attr_reader :modelname, :model
|
80
|
+
#Initialize will throw an exception if the model cannot be opened.
|
81
|
+
#
|
82
|
+
#RRTFinder uses Logger to log on STDOUT. Optionally you can pass a Logger instance
|
83
|
+
#and it will be used.
|
84
|
+
def initialize modelname="",logger=nil
|
85
|
+
logger_init(logger)
|
86
|
+
@modelname=modelname
|
87
|
+
@logger.debug("Opening model #{@modelname}")
|
88
|
+
@app=WIN32OLE.new(OLEAPP_NAME)
|
89
|
+
@model=@app.OpenModel(@modelname) unless modelname.empty?
|
90
|
+
raise FinderException.new(@modelname),"Model not loaded" unless @model
|
91
|
+
end
|
92
|
+
#open is used in conjuction with a block.
|
93
|
+
#
|
94
|
+
#It creates a RRTFinder instance and passes it to the block.
|
95
|
+
#At the end of the block the RRTFinder is stopped and invalidated.
|
96
|
+
#
|
97
|
+
#You can optionally pass a Logger instance to be used by the RRTFinder.
|
98
|
+
#
|
99
|
+
#Without a block the method is just an alias for RRTFinder#new
|
100
|
+
|
101
|
+
def self.open modelname,logger=nil #:yields: self
|
102
|
+
begin
|
103
|
+
fndr=self.new(modelname,logger)
|
104
|
+
if block_given?
|
105
|
+
begin
|
106
|
+
yield fndr
|
107
|
+
ensure
|
108
|
+
fndr.stop
|
109
|
+
end
|
110
|
+
else
|
111
|
+
return fndr
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
#Instructs the RRTFinder to load a new model into it's associated RRT instance.
|
116
|
+
#
|
117
|
+
#If modelname matches the current modelname or the RRTFinder is invalid...well, nothing will happen.
|
118
|
+
def reload modelname
|
119
|
+
begin
|
120
|
+
@modelname=modelname
|
121
|
+
@model=@app.openmodel(@modelname)
|
122
|
+
raise FinderException.new(@modelname),"Model not loaded" unless @model
|
123
|
+
end if @app && @app.CurrentModel.GetFileName.upcase!=modelname.upcase
|
124
|
+
end
|
125
|
+
#Stops the RRTFinder releasing the OLE interface and invalidating this RRTFinder instance.
|
126
|
+
#
|
127
|
+
#This method *must* be called to clean up resources unless you used RRTFinder#open with a block.
|
128
|
+
#
|
129
|
+
#If you don't call this method you will end up with a zombie RoseRT instance and a couple of MBs less memory.
|
130
|
+
#
|
131
|
+
#After calling stop the RRTFinder instance cannot be used again (most methods throw a FinderException).
|
132
|
+
#
|
133
|
+
#Unfortunately, there is no control on when the RRT instance is going to exit.
|
134
|
+
#
|
135
|
+
#Usually RRT instances that have been accessed will not exit until the application/script ends.
|
136
|
+
#Since RRT only allows three running instances, this means you can only reload a stopped finder twice.
|
137
|
+
def stop
|
138
|
+
@logger.debug("Stopping Finder")
|
139
|
+
@app.exit if @app
|
140
|
+
@app.ole_free()
|
141
|
+
@model=nil
|
142
|
+
@app=nil
|
143
|
+
end
|
144
|
+
#Shows the RRT UI for the associated OLE instance
|
145
|
+
#Makes the RRT UI associated with the RRTFinder visible.
|
146
|
+
#
|
147
|
+
#Throws a FinderException if no instance exists
|
148
|
+
def show
|
149
|
+
raise FinderException.new(@modelname),"This Finder instance is invalid" unless @app
|
150
|
+
@app.visible=true
|
151
|
+
end
|
152
|
+
#Hides the RRT UI for the associated OLE instance.
|
153
|
+
#
|
154
|
+
#Throws a FinderException if no instance exists
|
155
|
+
def hide
|
156
|
+
raise FinderException.new(@modelname),"This Finder instance is invalid" unless @app
|
157
|
+
@app.visible=false
|
158
|
+
end
|
159
|
+
#Returns the name of the model with which the RRTFinder is connected
|
160
|
+
#
|
161
|
+
#Alias for Finder#modelname
|
162
|
+
def name
|
163
|
+
return @modelname
|
164
|
+
end
|
165
|
+
def to_s
|
166
|
+
return "Active on #{@modelname}" if @model
|
167
|
+
return "Invalid for #{@modelname}"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
|
173
|
+
#Returns the pathname for the current model if an OLE server is present, nil otherwise
|
174
|
+
def self.current_model
|
175
|
+
begin
|
176
|
+
rt = WIN32OLE.connect(OLEAPP_NAME)
|
177
|
+
return rt.CurrentModel.GetFileName
|
178
|
+
rescue
|
179
|
+
return nil
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
#Provides read/write access to a RoseRT model
|
184
|
+
#
|
185
|
+
#See Writer for the 'write' interface
|
186
|
+
class RRTAccessor<RRTFinder
|
187
|
+
include Writer
|
45
188
|
end
|
46
189
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.3
|
|
3
3
|
specification_version: 1
|
4
4
|
name: rrt_ruby
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2005-10-
|
6
|
+
version: 0.3.0
|
7
|
+
date: 2005-10-19
|
8
8
|
summary: rrt_ruby is a Ruby library providing access to Rose RealTime models through RRTEI
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -29,10 +29,9 @@ authors:
|
|
29
29
|
files:
|
30
30
|
- lib/riva_ruby.rb
|
31
31
|
- lib/rrt_ruby.rb
|
32
|
-
- lib/rrt_ruby/
|
33
|
-
- lib/rrt_ruby/
|
34
|
-
- lib/rrt_ruby/
|
35
|
-
- lib/rrt_ruby/rrt_logical.rb
|
32
|
+
- lib/rrt_ruby/classes.rb
|
33
|
+
- lib/rrt_ruby/finder.rb
|
34
|
+
- lib/rrt_ruby/writer.rb
|
36
35
|
test_files: []
|
37
36
|
rdoc_options: []
|
38
37
|
extra_rdoc_files: []
|