123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- using System;
- using System.Collections.Generic;
- using System.Text.RegularExpressions;
- namespace sccdlib
- {
- public abstract class ObjectManagerBase
- {
- protected ControllerBase controller;
- EventQueue events = new EventQueue();
- Dictionary<RuntimeClassBase,InstanceWrapper> instances_map = new Dictionary<RuntimeClassBase,InstanceWrapper> ();
-
- public ObjectManagerBase (ControllerBase controller)
- {
- this.controller = controller;
- }
-
-
- public void addEvent (Event input_event, double time_offset = 0.0)
- {
- this.events.Add (input_event, time_offset);
- }
-
- public void broadcast (Event new_event)
- {
- foreach (RuntimeClassBase instance in this.instances_map.Keys)
- instance.addEvent(new_event);
- }
-
- public double getWaitTime()
- {
- //first get waiting time of the object manager's events
- double smallest_time = this.events.getEarliestTime();
- //check all the instances
- foreach (RuntimeClassBase instance in this.instances_map.Keys)
- smallest_time = Math.Min(smallest_time, instance.getEarliestEventTime());
- return smallest_time;
- }
-
- public void step (double delta)
- {
- this.events.decreaseTime(delta);
- foreach( Event e in this.events.popDueEvents())
- this.handleEvent (e);
- }
-
- private void handleEvent (Event handle_event)
- {
- string event_name = handle_event.getName ();
- if (event_name == "narrow_cast") {
- this.handleNarrowCastEvent(handle_event.getParameters());
- } else if (event_name == "broad_cast") {
- this.handleBroadCastEvent(handle_event.getParameters());
- } else if (event_name == "create_instance") {
- this.handleCreateEvent(handle_event.getParameters());
- } else if (event_name == "associate_instance") {
- this.handleAssociateEvent(handle_event.getParameters());
- } else if (event_name == "start_instance") {
- this.handleStartInstanceEvent(handle_event.getParameters());
- }
- }
-
- public void stepAll (double delta)
- {
- this.step(delta);
- foreach (RuntimeClassBase instance in this.instances_map.Keys)
- instance.step(delta);
- }
-
-
- public void start ()
- {
- foreach (RuntimeClassBase instance in this.instances_map.Keys)
- instance.start();
- }
-
- /// <summary>
- /// Processes the association reference.
- /// </summary>
- /// <returns>
- /// The association reference.
- /// </returns>
- /// <param name='input_string'>
- /// Input_string.
- /// </param>
- private List<Tuple<string, int>> processAssociationReference (string input_string)
- {
- if (input_string.Length == 0)
- throw new AssociationReferenceException("Empty association reference.");
- string[] path_string = input_string.Split (new char[] {'/'});
- Regex regex = new Regex(@"^([a-zA-Z_]\w*)(?:\[(\d+)\])?$");
-
- var result = new List<Tuple<string, int>>();
-
- foreach (string string_piece in path_string) {
- Match match = regex.Match (string_piece);
- if (match.Success ){
- string name = match.Groups[1].ToString ();
- int index;
- if (match.Groups[2].Success)
- int.TryParse(match.Groups[2].ToString(), out index);
- else
- index = -1;
- result.Add( new Tuple<string, int>(name,index));
- }else{
- throw new AssociationReferenceException("Invalid entry in association reference.");
- }
- }
- return result;
- }
-
- /// <summary>
- /// Gets the instances.
- /// </summary>
- /// <returns>
- /// The instances.
- /// </returns>
- /// <param name='source'>
- /// Source.
- /// </param>
- /// <param name='traversal_list'>
- /// Traversal_list.
- /// </param>
- private List<InstanceWrapper> getInstances (RuntimeClassBase source, List<Tuple<string, int>> traversal_list)
- {
- var currents = new List<InstanceWrapper> ();
- currents.Add (this.instances_map [source]);
- foreach (Tuple<string, int> tuple in traversal_list) {
- var nexts = new List<InstanceWrapper> ();
- foreach ( InstanceWrapper current in currents ){
- Association association = current.getAssociation (tuple.Item1);
- if (tuple.Item2 >= 0 )
- nexts.Add ( association.getInstance(tuple.Item2) );
- else if (tuple.Item2 == -1)
- nexts.AddRange ( association.getAllInstances() );
- else
- throw new AssociationReferenceException("Incorrect index in association reference.");
- }
- currents = nexts;
- }
- return currents;
- }
-
- /// <summary>
- /// Handles the start instance event.
- /// </summary>
- /// <param name='parameters'>
- /// [0] The instance the event originates from.
- /// [1] An association reference string targeting the instance to start.
- /// </param>
- private void handleStartInstanceEvent (object[] parameters)
- {
- if (parameters.Length != 2) {
- throw new ParameterException ("The start instance event needs 2 parameters.");
- } else {
- RuntimeClassBase source = (RuntimeClassBase) parameters[0];
- var traversal_list = this.processAssociationReference((string) parameters [1]);
-
- foreach( InstanceWrapper i in this.getInstances (source, traversal_list)){
- i.getInstance().start();
- }
- }
- }
-
- /// <summary>
- /// Handles the broad cast event.
- /// </summary>
- /// <param name='parameters'>
- /// [0] The event to be broadcasted.
- /// </param>
- private void handleBroadCastEvent(object[] parameters)
- {
- if (parameters.Length != 1 )
- throw new ParameterException ("The broadcast event needs 1 parameter.");
- this.broadcast((Event)parameters[0]);
- }
- private void handleCreateEvent (object[] parameters)
- {
- if (parameters.Length < 2) {
- throw new ParameterException ("The create event needs at least 2 parameters.");
- } else {
- RuntimeClassBase source = (RuntimeClassBase)parameters [0];
- string association_name = (string)parameters [1];
- Association association = this.instances_map[source].getAssociation (association_name);
- if (association.allowedToAdd ()){
- int constructor_parameters_length = parameters.Length -2;
- object[] constructor_parameters = new object[constructor_parameters_length];
- Array.Copy(parameters, 2, constructor_parameters, 0, constructor_parameters_length);
- InstanceWrapper new_instance_wrapper = this.createInstance(association.getClassName (), constructor_parameters);
- association.addInstance (new_instance_wrapper);
- source.addEvent(
- new Event(name: "instance_created", parameters : new object[] {association_name})
- );
- }else{
- source.addEvent (
- new Event(name: "instance_creation_error", parameters : new object[] {association_name})
- );
- }
- }
- }
-
-
- private void handleAssociateEvent (object[] parameters)
- {
- if (parameters.Length != 3) {
- throw new ParameterException ("The associate_instance event needs 3 parameters.");
- } else {
- RuntimeClassBase source = (RuntimeClassBase)parameters [0];
- List<InstanceWrapper> to_copy_list = this.getInstances (source, this.processAssociationReference ((string)parameters [1]));
- if (to_copy_list.Count != 1)
- throw new AssociationReferenceException ("Invalid source association reference.");
- InstanceWrapper wrapped_to_copy_instance = to_copy_list [0];
- List<Tuple<string,int>> dest_list = this.processAssociationReference ((string)parameters [2]);
- if (dest_list.Count == 0)
- throw new AssociationReferenceException ("Invalid destination association reference.");
- Tuple<string,int> last_tuple = dest_list [dest_list.Count - 1];
- if (last_tuple.Item2 != -1)
- throw new AssociationReferenceException ("Last association name in association reference should not be accompanied by an index.");
- dest_list.RemoveAt (dest_list.Count - 1);
- foreach (InstanceWrapper i in this.getInstances(source, dest_list)) {
- i.getAssociation (last_tuple.Item1).addInstance (wrapped_to_copy_instance);
- }
- }
- }
-
- private void handleNarrowCastEvent(object[] parameters)
- {
- if (parameters.Length != 3){
- throw new ParameterException ("The associate_instance event needs 3 parameters.");
- }else{
- RuntimeClassBase source = (RuntimeClassBase)parameters [0];
- Event cast_event = (Event) parameters[2];
- foreach (InstanceWrapper i in this.getInstances(source, this.processAssociationReference( (string) parameters[1])))
- i.getInstance ().addEvent(cast_event);
-
- }
- }
-
-
- protected abstract InstanceWrapper instantiate(string class_name, object[] construct_params);
-
- public InstanceWrapper createInstance(string class_name, object[] construct_params)
- {
- InstanceWrapper iw = this.instantiate(class_name, construct_params);
- if (iw != null)
- this.instances_map[iw.getInstance ()] = iw;
- return iw;
- }
- }
- }
|