| 1 | package desmoj.core.simulator; |
| 2 | |
| 3 | import java.util.ArrayList; |
| 4 | import java.util.LinkedList; |
| 5 | import java.util.List; |
| 6 | import org.apache.commons.collections.map.ReferenceMap; |
| 7 | |
| 8 | import desmoj.core.report.ReportManager; |
| 9 | import desmoj.core.report.Reporter; |
| 10 | |
| 11 | /** |
| 12 | * The model is supposed to carry references to all static modelcomponents |
| 13 | * associated to a model. These are modelcomponents like distributions and |
| 14 | * statistic counters. Note that placing all essential components inside the |
| 15 | * model class allows you to use object orientation to reuse this model to |
| 16 | * implement different versions of it using subclassing for changes necessary |
| 17 | * for using other modelling paradigms. This way models can be easily |
| 18 | * reimplemented following the process-, event-, transaction- or activity- |
| 19 | * oriented paradigm. Note that transaction- and activity-oriented modelling |
| 20 | * requires the higher process synchronization mechanisms (Res, Bin, WaitQueue, |
| 21 | * CondQueue) by Soenke Claassen. |
| 22 | * <p> |
| 23 | * The modelcomponents belonging to a model have to be instantiated in the |
| 24 | * <code>init()</code> method. They must not be instantiated in the model's |
| 25 | * constructor since most components need access to a valid experiment object. |
| 26 | * This can only be accessed after a model has been connected to an experiment |
| 27 | * using method <code>connectToExperiment(Experiment exp)</code> which |
| 28 | * implicitly calls the <code>init()</code> method after receiving the valid |
| 29 | * reference to an experiment. |
| 30 | * |
| 31 | * @version DESMO-J, Ver. 2.3.3 copyright (c) 2011 |
| 32 | * @author Tim Lechler |
| 33 | * |
| 34 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 35 | * you may not use this file except in compliance with the License. You |
| 36 | * may obtain a copy of the License at |
| 37 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 38 | * |
| 39 | * Unless required by applicable law or agreed to in writing, software |
| 40 | * distributed under the License is distributed on an "AS IS" |
| 41 | * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| 42 | * or implied. See the License for the specific language governing |
| 43 | * permissions and limitations under the License. |
| 44 | * |
| 45 | */ |
| 46 | public abstract class Model extends Reportable { |
| 47 | |
| 48 | /** |
| 49 | * The experiment this model is connected to. |
| 50 | */ |
| 51 | private Experiment _myExperiment; |
| 52 | |
| 53 | /** |
| 54 | * The map with all entities and their identifiers. |
| 55 | */ |
| 56 | private ReferenceMap _entityMap; |
| 57 | |
| 58 | /** |
| 59 | * True if this is the main model (not a submodel to another model), false |
| 60 | * for submodels. |
| 61 | */ |
| 62 | boolean isMainModel; |
| 63 | |
| 64 | /** |
| 65 | * The current number of the created entities. |
| 66 | */ |
| 67 | private long _numberOfEntitiesCreated; |
| 68 | |
| 69 | /** |
| 70 | * Dynamic List containing all associated submodels. |
| 71 | */ |
| 72 | private ArrayList<Model> _subModels; |
| 73 | |
| 74 | /** |
| 75 | * Dynamic List containing all reportable components of this model. |
| 76 | */ |
| 77 | private ArrayList<Reportable> _reportables; |
| 78 | |
| 79 | /** |
| 80 | * The parameter manager |
| 81 | */ |
| 82 | private ModelParameterManager _paramManager; |
| 83 | |
| 84 | /** |
| 85 | * Constructs a model, with the given name and parameters for report and |
| 86 | * trace files. |
| 87 | * |
| 88 | * @param name |
| 89 | * java.lang.String : The name of this model |
| 90 | * @param owner |
| 91 | * Model : The main model this model is associated to |
| 92 | * @param showInTrace |
| 93 | * boolean : Flag for showing this model in trace-files. Set it |
| 94 | * to <code>true</code> if model should show up in trace, |
| 95 | * <code>false</code> if model should not be shown in trace. |
| 96 | */ |
| 97 | public Model(Model owner, String name, boolean showInReport, |
| 98 | boolean showInTrace) { |
| 99 | |
| 100 | super(owner, name, showInReport, showInTrace); // create a reportable |
| 101 | |
| 102 | // init data structures |
| 103 | _subModels = new ArrayList<Model>(); // create empty Vector for subModels |
| 104 | _reportables = new ArrayList<Reportable>(); // create empty Vector for reportables |
| 105 | |
| 106 | if (owner != null) { // check if this is a submodel |
| 107 | this.isMainModel = false; |
| 108 | owner.registerSubModel(this); |
| 109 | // register as submodel at owner model |
| 110 | } else { |
| 111 | this.isMainModel = true; |
| 112 | } |
| 113 | |
| 114 | _paramManager = new ParameterManager(); // create ParameterManager |
| 115 | |
| 116 | _numberOfEntitiesCreated = 0L; |
| 117 | |
| 118 | _entityMap = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK); |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * Checks the given modelcomponent for compatibility. Needed exclusively |
| 123 | * when submodels are present that want to share modelcomponents between |
| 124 | * them. The standard implementation only checks if the modelcomponent |
| 125 | * <code>other</code> belongs to <code>this</code> model. For use with |
| 126 | * multiple models, the user has to specify which other models are |
| 127 | * compatible to this model by overloading this method. |
| 128 | * |
| 129 | * @return boolean : Returns <code>true</code> if the given modelcomponent |
| 130 | * is compatible to this model, <code>false</code> otherwise. |
| 131 | * @param other |
| 132 | * ModelComponent : The modelcomponent that needs to be checked |
| 133 | * for compatibility to this model. |
| 134 | */ |
| 135 | protected boolean checkCompatibility(ModelComponent other) { |
| 136 | |
| 137 | return (this == other.getModel()); // check for same owner |
| 138 | |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * Connects this model to an experiment. The given experiment must not |
| 143 | * already be connected to some other model. Otherwise an errormessage will |
| 144 | * be given and the experiment will be stopped. Since a model that is not |
| 145 | * yet connected has no access to the experiment's messaging subsystem, |
| 146 | */ |
| 147 | public void connectToExperiment(Experiment exp) { |
| 148 | |
| 149 | if (exp == null) { |
| 150 | sendWarning("Can not connect to a <code>null</code> Experiment! " |
| 151 | + "Command ignored.", "Model : " + getName() |
| 152 | + " Method: void connectToExperiment" + "(Experiment exp)", |
| 153 | "The experiment reference passed is a null reference!", |
| 154 | "Make sure to use valid references only."); |
| 155 | return; // no connection possible. |
| 156 | } |
| 157 | |
| 158 | if (!isMainModel()) { // only main model should register at experiment |
| 159 | sendWarning("Can not connect to Experiment " + exp.getName() + "! " |
| 160 | + "Command ignored.", "Model : " + getName() |
| 161 | + " Method: void connectToExperiment" + "(Experiment exp)", |
| 162 | "The model to be connected is already submodel to model : " |
| 163 | + getModel().getName(), |
| 164 | "Only ,main models are allowed to be connected to an " |
| 165 | + "experiment"); |
| 166 | return; // model is no main model |
| 167 | } |
| 168 | |
| 169 | if (exp.isConnected()) { |
| 170 | sendWarning("Can not connect to Experiment " + exp.getName() + "! " |
| 171 | + "Command ignored.", "Model : " + getName() |
| 172 | + " Method: void connectToExperiment" + "(Experiment exp)", |
| 173 | "The experiment to connect to is itself already connected " |
| 174 | + "to model : " + exp.getModel(), |
| 175 | "Only one main model can be connected to an experiment at " |
| 176 | + "a time."); |
| 177 | return; // no connection possible. |
| 178 | } |
| 179 | |
| 180 | if (_myExperiment != null) { |
| 181 | sendWarning("Can not connect to Experiment " + exp.getName() + "! " |
| 182 | + "Command ignored.", "Model : " + getName() |
| 183 | + " Method: void connectToExperiment" + "(Experiment exp)", |
| 184 | "The model is already connected to Experiment : " |
| 185 | + _myExperiment.getName() + "!", |
| 186 | "A model can only be connected to just one Experiment."); |
| 187 | return; |
| 188 | } |
| 189 | |
| 190 | // set the experiment reference |
| 191 | _myExperiment = exp; |
| 192 | |
| 193 | // register at Experiment |
| 194 | _myExperiment.registerModel(this); |
| 195 | |
| 196 | // set the Experiment parameter at all submodels if necessary |
| 197 | if (!_subModels.isEmpty()) { |
| 198 | |
| 199 | for (Model m : _subModels) { |
| 200 | m.setConnectedExperiment(exp); |
| 201 | } |
| 202 | |
| 203 | } |
| 204 | |
| 205 | // initialize the components of the main model |
| 206 | init(); |
| 207 | // initialize the submodels recursively |
| 208 | doSubmodelInit(); |
| 209 | // reset the model and all submodels recursively |
| 210 | reset(); |
| 211 | |
| 212 | } |
| 213 | |
| 214 | /** |
| 215 | * Creates the default reporter associated with this model. The default |
| 216 | * reporter returned by this method just prints the model's description as |
| 217 | * implemented in method <code>description()</code> and appends the |
| 218 | * simulation time of the last reset. If the user's model offers more |
| 219 | * information, create a special class derived from class |
| 220 | * <code>desmoj.report.ModelReporter</code> to extract and present that |
| 221 | * extra information. |
| 222 | * |
| 223 | * @return Reportable : The reporter associated with this model |
| 224 | */ |
| 225 | public Reporter createReporter() { |
| 226 | |
| 227 | // has to be the special reporter designed for this model |
| 228 | return new desmoj.core.report.ModelReporter(this); |
| 229 | |
| 230 | } |
| 231 | |
| 232 | /** |
| 233 | * Should return the description of the model. Implement this method to |
| 234 | * document the model's intent, creator, date and all other information that |
| 235 | * needs to be published about this model in a report. Please use it |
| 236 | * generously, other people interested in your model will thank you. |
| 237 | * |
| 238 | * @return java.lang.String : The description of the model as a text String |
| 239 | */ |
| 240 | public abstract String description(); |
| 241 | |
| 242 | /** |
| 243 | * Implement this method to schedule the entities and/or events needed for |
| 244 | * your model to start in a defined setting. If a model is connected to an |
| 245 | * experiment and started without any initial schedules, it will not run |
| 246 | * since no events to process are on the scheduler's event-list. This method |
| 247 | * is called automatically by the framework when the experiment's |
| 248 | * <code>start()</code> method is called. |
| 249 | */ |
| 250 | public abstract void doInitialSchedules(); |
| 251 | |
| 252 | /** |
| 253 | * Calls the <code>init()</code> method of all registered |
| 254 | * submodels of the current model. Subsequently calls the |
| 255 | * <code>init()</code> method of all registered submodels |
| 256 | * of every submodel. |
| 257 | */ |
| 258 | void doSubmodelInit() { |
| 259 | |
| 260 | if (!this.hasSubModels()) |
| 261 | return; // no submodels registered here |
| 262 | else { |
| 263 | |
| 264 | for (Model m : _subModels) { // loop submodels |
| 265 | m.init(); // init submodel |
| 266 | m.doSubmodelInit(); // init submodels of submodels |
| 267 | } |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | /** |
| 272 | * Calls the <code>doInitialSchedules()</code> method of all registered |
| 273 | * submodels of the current model. Subsequently calls the |
| 274 | * <code>doSubmodelSchedules()</code> method of all registered submodels |
| 275 | * of every submodel. |
| 276 | */ |
| 277 | void doSubmodelSchedules() { |
| 278 | |
| 279 | if (!this.hasSubModels()) |
| 280 | return; // no submodels registered here |
| 281 | else { |
| 282 | |
| 283 | for (Model m : _subModels) { // loop submodels |
| 284 | m.doInitialSchedules(); // initial schedules for the submodel |
| 285 | m.doSubmodelSchedules(); // initial schedules for potential submodels of the submodel |
| 286 | } |
| 287 | |
| 288 | } |
| 289 | } |
| 290 | |
| 291 | /** |
| 292 | * Returns the entity to the belonging identifier. |
| 293 | * @return Entity : The class will return the |
| 294 | * <code>Entity</code> or null if no such exists. |
| 295 | */ |
| 296 | public Entity getEntity(long ident) |
| 297 | { |
| 298 | return (Entity) _entityMap.get(Long.valueOf(ident)); |
| 299 | } |
| 300 | |
| 301 | /** |
| 302 | * Returns a list of this model's entities. |
| 303 | * |
| 304 | * @param includeSubmodels |
| 305 | * boolean : Do include (true) or exclude (false) submodels' entities in the list. |
| 306 | * |
| 307 | * @return List<Entity> : The class will return a list of all existing objects of |
| 308 | * <code>Entity</code> or null if no list exists. |
| 309 | */ |
| 310 | public List<Entity> getEntities(boolean includeSubmodels) |
| 311 | { |
| 312 | List<Entity> list = new LinkedList<Entity>(); |
| 313 | list.addAll(_entityMap.values()); |
| 314 | |
| 315 | if (includeSubmodels) { |
| 316 | for (Model submodel : this._subModels) { |
| 317 | list.addAll(submodel.getEntities(true)); |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | return list; |
| 322 | } |
| 323 | |
| 324 | /** |
| 325 | * Returns the experiment that is connected to this model or |
| 326 | * <code>null</code> if the model is not yet connected to an experiment. |
| 327 | * |
| 328 | * @return Experiment : The experiment that this model is connected to or |
| 329 | * <code>null</code> if no connection is established |
| 330 | */ |
| 331 | public Experiment getExperiment() { |
| 332 | |
| 333 | if (this.isMainModel()) { |
| 334 | |
| 335 | return _myExperiment; |
| 336 | |
| 337 | } else { |
| 338 | |
| 339 | return this.getModel().getExperiment(); |
| 340 | |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | /** |
| 345 | * Returns a copy of the dynamic list containing all reportable |
| 346 | * components of this model. |
| 347 | * |
| 348 | * @return reportables : A list containing all reportable |
| 349 | * components of this model. |
| 350 | */ |
| 351 | public List<Reportable> getReportables() { |
| 352 | return new ArrayList<Reportable>(this._reportables); |
| 353 | } |
| 354 | |
| 355 | /** |
| 356 | * Returns the Model's viewpoint of the ParameterManager |
| 357 | * |
| 358 | * @return ModelParameterManager : The ParameterManager |
| 359 | */ |
| 360 | public ModelParameterManager getParameterManager() |
| 361 | { |
| 362 | return _paramManager; |
| 363 | } |
| 364 | |
| 365 | /** |
| 366 | * Shows, if there are submodels registered with this model. |
| 367 | * |
| 368 | * @return boolean : True, if there is at least one submodel registered at |
| 369 | * this Model, flase if there are no submodels |
| 370 | */ |
| 371 | public boolean hasSubModels() { |
| 372 | |
| 373 | return !_subModels.isEmpty(); // checks for some submodels in vector |
| 374 | |
| 375 | } |
| 376 | |
| 377 | /** |
| 378 | * Implement this method to do initialization work for your model. All |
| 379 | * ModelComponents associated with this model are supposed to be |
| 380 | * instantiated in this method. |
| 381 | * <p> |
| 382 | * <em>Caution! Do not use the Model's constructor method to instantiate your |
| 383 | * modelcomponents!</em> |
| 384 | * <br> |
| 385 | * This prevents the modelcomponents to get contact to the associated |
| 386 | * Experiment since a Model can only be connected to an Experiment after |
| 387 | * itself has been instantiated correctly. Thus it is necessary to put all |
| 388 | * initialization and instantiation work into this method. Do not use this |
| 389 | * method to do the initial schedules needed for the scheduler to start |
| 390 | * with. Use method <code>doInitialSchedules()</code> instead. If there |
| 391 | * are no events scheduled in the event-list, the scheduler will stop the |
| 392 | * simulation immediately because there is nothing for him to do. If you are |
| 393 | * using submodels, take care that each of the submodels has its own |
| 394 | * <code>init</code> method properly set up. |
| 395 | */ |
| 396 | public abstract void init(); |
| 397 | |
| 398 | /** |
| 399 | * Initializes the model by calling method <code>init()</code> to set up |
| 400 | * all model related components as specified in that method. After |
| 401 | * initializing the model, the given ModelOption's <code>setOption()</code> |
| 402 | * method is called with this model as parameter. This enables the user to |
| 403 | * specify different model parameter settings for different experiments. It |
| 404 | * even allows automated parameter variation to give a small but handy aid |
| 405 | * for model optimization. Implement the ModelOptions to set the parameters |
| 406 | * for your model. Make sure to react properly on the ModelOptions given. |
| 407 | * Note that specifiying ModelOptions is up to the user. |
| 408 | * |
| 409 | * @param options |
| 410 | * ModelOptions : The parameter settings for this model |
| 411 | */ |
| 412 | public void init(ModelOptions options) { |
| 413 | |
| 414 | this.init(); // just call the other init after dealing with the |
| 415 | // options |
| 416 | options.setOptions(this); |
| 417 | |
| 418 | } |
| 419 | |
| 420 | /** |
| 421 | * Shows if this model has already been connected to an experiment. |
| 422 | * |
| 423 | * @return boolean : Is <code>true</code>, if model is connected to an |
| 424 | * experiment, <code>false</code> otherwise |
| 425 | */ |
| 426 | public boolean isConnected() { |
| 427 | |
| 428 | return (_myExperiment != null); // no experiment connected |
| 429 | |
| 430 | } |
| 431 | |
| 432 | /** |
| 433 | * Shows if this model is a main model and thus is not submodel of other |
| 434 | * models. |
| 435 | * |
| 436 | * @return boolean : Returns <code>true</code> if the model is a main |
| 437 | * model, <code>false</code> if it is a submodel of other models |
| 438 | */ |
| 439 | public boolean isMainModel() { |
| 440 | |
| 441 | return this.isMainModel; |
| 442 | |
| 443 | } |
| 444 | |
| 445 | /** |
| 446 | * Shows if this model is submodel to another model and thus is not the main |
| 447 | * models. |
| 448 | * |
| 449 | * @return boolean : Returns <code>true</code> if the model is a submodel |
| 450 | * of other models, <code>false</code> if it is a main model |
| 451 | */ |
| 452 | public boolean isSubModel() { |
| 453 | |
| 454 | return !this.isMainModel; |
| 455 | } |
| 456 | |
| 457 | /** |
| 458 | * Links an entity with an unique identification number. |
| 459 | * |
| 460 | * @param e |
| 461 | * Entity : The new Entity to link with an unique identification number. |
| 462 | * |
| 463 | * @return long : Unique identification number. |
| 464 | */ |
| 465 | long linkWithIdentNumber(Entity e) |
| 466 | { |
| 467 | _numberOfEntitiesCreated++; |
| 468 | _entityMap.put(_numberOfEntitiesCreated, e); |
| 469 | return _numberOfEntitiesCreated; |
| 470 | } |
| 471 | |
| 472 | /** |
| 473 | * Registers a reportable at this model. Reports can only be drawn, if the |
| 474 | * reportbale is registered at his model. |
| 475 | * |
| 476 | * @param r |
| 477 | * desmoj.core.simulator.Reportable : The reportable to be registered |
| 478 | */ |
| 479 | void register(Reportable r) { |
| 480 | |
| 481 | if (r == null) |
| 482 | return; // do not accept null values |
| 483 | else |
| 484 | _reportables.add(r); |
| 485 | |
| 486 | } |
| 487 | |
| 488 | /** |
| 489 | * Registers another model as submodel of this model. |
| 490 | * |
| 491 | * @param subModel |
| 492 | * Model : The model to be registerd as a submodel |
| 493 | */ |
| 494 | void registerSubModel(Model subModel) { |
| 495 | |
| 496 | if (subModel == null) { |
| 497 | sendWarning("Can't register Submodel!", "Model : " + getName() |
| 498 | + " Method: registerSubModel(Model " + "subModel)", |
| 499 | "The SubModel given as parameter is a null reference.", |
| 500 | "Be sure to have a valid SubModel reference before calling " |
| 501 | + "this method."); |
| 502 | return; // exit |
| 503 | } |
| 504 | |
| 505 | _subModels.add(subModel); |
| 506 | |
| 507 | } |
| 508 | |
| 509 | /** |
| 510 | * Produces a report about the model and all its related modelcomponents and |
| 511 | * submodels. It registers the model's reporter and all other reporters at |
| 512 | * the experiment's reportmanager to produce the report output. The |
| 513 | * reporters are ordered into the reportmanager returned with this model's |
| 514 | * reporter first, followed by all reportable's reporters. After this |
| 515 | * section, all submodel's reporters are inserted according to the order |
| 516 | * they were attached to this model. Each submodel's section is sorted using |
| 517 | * the criteria above. Thus all reporters a re separated by model to prevent |
| 518 | * confusion. |
| 519 | * |
| 520 | * @return Enumeration : The Enumeration carrying all reporters available |
| 521 | * from this model |
| 522 | */ |
| 523 | List<Reporter> report() { |
| 524 | |
| 525 | // create the reportmanager necessary for sorting all reporters |
| 526 | ReportManager repMan = new ReportManager(getName() + "_ReportManager"); |
| 527 | |
| 528 | // register this model's reporter |
| 529 | repMan.register(createReporter()); |
| 530 | |
| 531 | // register all modelcomponent's reporters |
| 532 | // in case they are set to produce a report output |
| 533 | for (Reportable r : _reportables) { // loop reportables |
| 534 | if (r.reportIsOn()) |
| 535 | repMan.register(r.createReporter()); |
| 536 | } |
| 537 | |
| 538 | // register all submodel's reporters |
| 539 | List<Reporter> subReporters; |
| 540 | // buffer for submodel-reportmanagers returned |
| 541 | |
| 542 | for (Model m : _subModels) { // loop submodels |
| 543 | |
| 544 | subReporters = m.report(); |
| 545 | |
| 546 | // add all reporters from the ordered enumeration at last position |
| 547 | // of repMan |
| 548 | for (Reporter r : subReporters) { |
| 549 | repMan.addLast(r); |
| 550 | } |
| 551 | } |
| 552 | |
| 553 | return repMan.elements(); |
| 554 | |
| 555 | } |
| 556 | |
| 557 | /** |
| 558 | * Resets the statistic counters of this model and of all its registered |
| 559 | * reportables. Also calls all submodels's <code>reset()</code> methods. |
| 560 | */ |
| 561 | public void reset() { |
| 562 | |
| 563 | // reset this model |
| 564 | super.reset(); // reset the own obs & resetAt variables |
| 565 | |
| 566 | // reset all reportables registered here |
| 567 | if (_reportables.isEmpty()) |
| 568 | return; // no reportables registered |
| 569 | else { |
| 570 | |
| 571 | for (Reportable r : _reportables) { // loop reportables |
| 572 | r.reset(); |
| 573 | // reset each registered |
| 574 | } |
| 575 | |
| 576 | } |
| 577 | |
| 578 | // reset all registered submodels |
| 579 | if (_subModels.isEmpty()) |
| 580 | return; // no reportables registered |
| 581 | else { |
| 582 | |
| 583 | for (Model m : _subModels) { // loop submodels |
| 584 | m.reset(); |
| 585 | // reset each registered |
| 586 | } |
| 587 | |
| 588 | } |
| 589 | |
| 590 | } |
| 591 | |
| 592 | /** |
| 593 | * Connects submodels to the experiment given. This method is called by the |
| 594 | * main model, when submodels register themselves at the main model. |
| 595 | * |
| 596 | * @param e |
| 597 | * desmoj.Experiment : The experiment to connect this model to |
| 598 | */ |
| 599 | void setConnectedExperiment(Experiment e) { |
| 600 | |
| 601 | if (e == null) { |
| 602 | sendWarning( |
| 603 | "Can not connect to experiment! Command ignored.", |
| 604 | "Model : " + getName() + " Method: " |
| 605 | + "void setConnectedExperiment (Experiment e)", |
| 606 | "The given Esperiment parameter contained a null reference", |
| 607 | "Be sure to always give valid parameters."); |
| 608 | return; // do nothing |
| 609 | } |
| 610 | |
| 611 | if (isSubModel()) { // this is a submodel |
| 612 | _myExperiment = e; |
| 613 | return; |
| 614 | } else { // this is no submodel |
| 615 | sendWarning("Can not connect to experiment! Command ignored.", |
| 616 | "Model : " + getName() + " Method: void " |
| 617 | + "method setConnectedExperiment" |
| 618 | + "(Experiment e)", |
| 619 | "This model is not a submodel.", |
| 620 | "Only submodels can be connected to an experiment using " |
| 621 | + "this method."); |
| 622 | return; // do nothing |
| 623 | } |
| 624 | |
| 625 | } |
| 626 | |
| 627 | /** |
| 628 | * Sets the current model to be the main model by setting the |
| 629 | * <code>owner</code> reference to itself. |
| 630 | */ |
| 631 | void setMain() { |
| 632 | |
| 633 | setOwner(this); |
| 634 | |
| 635 | } |
| 636 | |
| 637 | } |