protected void LogImage(string url, string fn, string keywords, string title, string explanation, List <string> errors)
        {
            ICarrier recordCarrier = CreateAPODRecordCarrier();

            recordCarrier.Signal.URL.Value = url;
            recordCarrier.Signal.ImageFilename.Filename = fn;
            recordCarrier.Signal.Keywords.Text.Value    = keywords;
            recordCarrier.Signal.Explanation.Text.Value = explanation;
            recordCarrier.Signal.Title.Text.Value       = title;
            recordCarrier.Signal.Errors = String.Join(", ", errors.ToArray());

            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("DatabaseRecord");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("DatabaseRecord");

            signal.TableName = "APOD";
            signal.Action    = "insert";
            signal.Row       = recordCarrier;
            rsys.CreateCarrier(this, protocol, signal);

            // Use the debug message receptor to display error counts.
            if (errors.Count > 0)
            {
                ++totalErrors;
                ISemanticTypeStruct dbgMsgProtocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("DebugMessage");
                dynamic             dbgMsgSignal   = rsys.SemanticTypeSystem.Create("DebugMessage");
                dbgMsgSignal.Message = totalErrors.ToString() + ": " + recordCarrier.Signal.Errors;
                rsys.CreateCarrier(this, dbgMsgProtocol, dbgMsgSignal);
            }
        }
Exemple #2
0
 public Carrier(ISemanticTypeStruct protocol, string protocolPath, dynamic signal, ICarrier parentCarrier)
 {
     Protocol      = protocol;
     Signal        = signal;
     ProtocolPath  = protocolPath;
     ParentCarrier = parentCarrier;
 }
Exemple #3
0
        /// <summary>
        /// Clone the element of the source signal into a new destination signal.
        /// This does NOT clone the signal--it is designed to clone the specific child semantic element of the supplied signal.
        /// </summary>
        public dynamic Clone(dynamic sourceSignal, ISemanticElement childElem)
        {
            dynamic subsignal = null;

            if (sourceSignal != null)
            {
                PropertyInfo pi  = sourceSignal.GetType().GetProperty(childElem.Name);                                  // Get the property of the source's sub-type, which will/must be a semantic element
                object       val = pi.GetValue(sourceSignal);                                                           // Get the instance of the semantic element we are cloning.

                // A sub-ST can be null, especially as produced by the persistence engine with outer joins.
                if (val != null)
                {
                    subsignal = Create(childElem.Name);                                                                                                 // Create the sub-signal
                    ISemanticTypeStruct subSemStruct = GetSemanticTypeStruct(childElem.Name);

                    foreach (INativeType nativeType in subSemStruct.NativeTypes)
                    {
                        // Copy any native types.
                        object ntVal = nativeType.GetValue(this, val);
                        nativeType.SetValue(this, subsignal, ntVal);
                    }

                    // Recurse drilling into semantic types of this type and copying any potential native types.
                    foreach (ISemanticElement semanticElem in subSemStruct.SemanticElements)
                    {
                        dynamic      se    = Clone((dynamic)val, semanticElem);                                                 // Clone the sub-semantic type
                        PropertyInfo piSub = subsignal.GetType().GetProperty(semanticElem.Name);                                // Get the PropertyInfo for this type.
                        piSub.SetValue(subsignal, se);                                                                          // Assign the instance of the created semantic type to the value for this property.
                    }
                }
            }

            return(subsignal);
        }
Exemple #4
0
        protected void Emit(string protocol, DataTable data, string url)
        {
            data.ForEach(row =>
            {
                CreateCarrierIfReceiver(protocol, signal =>
                {
                    signal.URL.Value = url;                                     // .Value because this is a semantic element and Value drills into the implementing native type.
                    // Use the protocol as the driver of the fields we want to emit.
                    ISemanticTypeStruct st = rsys.SemanticTypeSystem.GetSemanticTypeStruct(protocol);

                    st.AllTypes.ForEach(se =>
                    {
                        // Sometimes a column will be missing.
                        if (data.Columns.Contains(se.Name))
                        {
                            object val = row[se.Name];

                            if (val != null && val != DBNull.Value)
                            {
                                se.SetValue(rsys.SemanticTypeSystem, signal, val);
                            }
                        }
                    });
                });
            });
        }
Exemple #5
0
        protected void RecurseGetFullyQualifiedNativeTypes(ISemanticTypeStruct st, string stack, string alias, bool isUnique, int ordinality, bool recurse, List <IFullyQualifiedNativeType> fqntList)
        {
            foreach (INativeType nativeType in st.NativeTypes)
            {
                string ntalias = (!String.IsNullOrEmpty(alias) ? alias : nativeType.Alias);
                fqntList.Add(new FullyQualifiedNativeType()
                {
                    FullyQualifiedName = stack + "." + nativeType.Name,
                    NativeType         = nativeType,
                    Alias       = ntalias,
                    UniqueField = nativeType.UniqueField || isUnique,
                    Ordinality  = nativeType.Ordinality + ordinality
                });
            }

            if (recurse)
            {
                foreach (ISemanticElement childElem in st.SemanticElements)
                {
                    stack = stack + "." + childElem.Name;                                       // push
                    ISemanticTypeStruct stChild = GetSemanticTypeStruct(childElem.Name);

                    // Check first if the child element has an alias.  If so (and no prior alias is overriding) then use the alias defined in the element.
                    string newAlias = (!String.IsNullOrEmpty(alias) ? alias : childElem.Alias);

                    // Check next if the semantic type itself has an alias.  If so (and no prior alias is overriding) then use the alias defined for the semantic type of the child element.
                    // Confusing, isn't it?
                    newAlias = (!String.IsNullOrEmpty(newAlias) ? newAlias : stChild.Alias);

                    int newOrdinality = ((ordinality != 0) ? ordinality : childElem.Ordinality);
                    RecurseGetFullyQualifiedNativeTypes(stChild, stack, newAlias, isUnique || stChild.Unique, newOrdinality, recurse, fqntList);
                    stack = stack.LeftOfRightmostOf('.');                                       // pop
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Create the table and column definitions for the protocol.
        /// </summary>
        protected void CreateViewerTable(TabPage tabPage, string protocolName)
        {
            DataTable           dt = new DataTable();
            ISemanticTypeStruct st = rsys.SemanticTypeSystem.GetSemanticTypeStruct(protocolName);

            st.AllTypes.ForEach(t =>
            {
                DataColumn dc = new DataColumn(t.Name, t.GetImplementingType(rsys.SemanticTypeSystem));
                dt.Columns.Add(dc);
            });

            DataView     dv  = new DataView(dt);
            DataGridView dgv = new DataGridView();

            dgv.Dock = DockStyle.Fill;
            dgv.AutoSizeColumnsMode   = DataGridViewAutoSizeColumnsMode.Fill;
            dgv.DataSource            = dv;
            dgv.AllowUserToAddRows    = false;
            dgv.AllowUserToDeleteRows = false;
            dgv.ReadOnly          = true;
            dgv.SelectionMode     = DataGridViewSelectionMode.FullRowSelect;
            dgv.RowHeadersVisible = false;
            dgv.Tag = protocolName;
            dgv.CellContentDoubleClick += OnCellContentDoubleClick;

            tabPage.Controls.Add(dgv);
            protocolGridMap[protocolName] = dgv;
        }
Exemple #7
0
        /// <summary>
        /// Remove protocols no longer of interest and add new protocols.
        /// </summary>
        protected void UpdateReceivedProtocolsAndTabs()
        {
            // Assume we will remove all protocols.
            List <string> protocolsToBeRemoved = new List <string>(receiveProtocols.Select(p => p.Protocol).ToList());

            foreach (DataRow row in dt.Rows)
            {
                string protocol = row[1].ToString();

                if (!protocolsToBeRemoved.Contains(protocol))                                   // does it currently exist or not?
                {
                    AddReceiveProtocol(protocol);
                    // Add emitters for semantic elements in the receive protocol that we can emit when the user double-clicks.
                    ISemanticTypeStruct st = rsys.SemanticTypeSystem.GetSemanticTypeStruct(protocol);
                    st.SemanticElements.ForEach(se => AddEmitProtocol(se.Name));

                    // Create the tab page.
                    TabPage tabPage = CreateTabPage(row[0].ToString(), protocol);
                    CreateViewerTable(tabPage, protocol);
                }

                protocolsToBeRemoved.Remove(protocol);                           // nope, we don't remove this one.
            }

            protocolsToBeRemoved.ForEach(p =>
            {
                RemoveReceiveProtocol(p);
                tcProtocols.TabPages.Remove(protocolTabPageMap[p]);
                protocolTabPageMap.Remove(p);
                protocolGridMap.Remove(p);
            });
        }
Exemple #8
0
 /// <summary>
 /// Create a carrier of the specified protocol and signal if a receiver currently exists.
 /// Note that because a carrier might not be created, there is no return value for this method.
 /// </summary>
 /// <param name="from">The source receptor.  Cay be null.</param>
 /// <param name="protocol">The protocol.</param>
 /// <param name="signal">The signal in the protocol's format.</param>
 public void CreateCarrierIfReceiver(IReceptorInstance from, ISemanticTypeStruct protocol, dynamic signal)
 {
     if (TargetReceptorExistsFor(ReceptorFromInstance(from), protocol))
     {
         CreateCarrier(from, protocol, signal);
     }
 }
Exemple #9
0
 protected void CreateCarrierIfReceiver(IReceptorInstance from, ISemanticTypeStruct protocol, string protocolPath, dynamic signal, ICarrier parentCarrier, bool emitSubElements = true)
 {
     if (from.GetEnabledEmittedProtocols().Any(p => p.Protocol == protocol.DeclTypeName))
     {
         if (TargetReceptorExistsFor(ReceptorFromInstance(from), protocol, protocol.DeclTypeName == protocolPath))
         {
             // This call will recurse for us.
             // CreateCarrier(IReceptorInstance from, ISemanticTypeStruct protocol, string protocolPath, dynamic signal, bool stopRecursion, bool isSystemMessage = false, ICarrier parentCarrier = null)
             CreateCarrier(from, protocol, protocolPath, signal, false, false, parentCarrier, emitSubElements);
         }
         else
         {
             if (emitSubElements)
             {
                 // Recurse into SE's of the protocol and emit carriers for those as well, if a receiver exists.
                 // We do this even if there isn't a target for the top-level receptor.
                 // However, we do create a Carrier instance as the parent so the child can reference it if necessary.
                 Carrier carrier = new Carrier(protocol, protocolPath, signal, parentCarrier);
                 CreateCarriersForSemanticElements(from, protocol, protocolPath, signal, false, carrier);
             }
         }
     }
     else
     {
         if (emitSubElements)
         {
             // Create a Carrier instance as the parent so the child can reference it if necessary.
             Carrier carrier = new Carrier(protocol, protocolPath, signal, parentCarrier);
             CreateCarriersForSemanticElements(from, protocol, protocolPath, signal, false, carrier);
         }
     }
 }
Exemple #10
0
        /// <summary>
        /// Returns true if there is an enabled target from the specified receptor with the specified protocol.
        /// </summary>
        protected bool TargetReceptorExistsFor(IReceptor from, ISemanticTypeStruct protocol, bool isRoot)
        {
            bool ret = false;

            // Some bullet proofing that was revealed in unit testing.
            if (from != null)
            {
                List <IReceptorConnection> targets = new List <IReceptorConnection>();
                if (MasterReceptorConnectionList.TryGetValue(from, out targets))
                {
                    // This annoying piece of code assumes that a receptor will have only one connection between "from" to "to".
                    // In the case of the semantic database, a "from" receptor can have multiple connections with the same semantic database receptor.
                    // In other words, the returned list consists of [n] identical instances, where [n] is the number of different protocols from "from" to the target receptor.
                    // To fix this problem, we get only the distinct instances.
                    targets = targets.Distinct().ToList();
                    // We're only interested in enabled receptors, and we ignore ourselves.
                    ret = targets.Any(r => r.Receptor != from &&
                                      r.Receptor.Instance.Enabled &&
                                      (!r.RootOnly || isRoot) &&                                // root protocol or we don't care if it's not the root.
                                      r.Receptor.Instance.GetEnabledReceiveProtocols().Select(rp => rp.Protocol).Contains(protocol.DeclTypeName));
                }

                if (!ret)
                {
                    // check protocol map for receivers that are not the issuing receptor, ignoring ourselves.
                    ret = protocolReceptorMap.Any(kvp => (kvp.Key == protocol.DeclTypeName) &&
                                                  kvp.Value.Any(r => (r.Receptor != from) &&
                                                                (!r.RootOnly || isRoot) &&       // root protocol or we don't care if it's not the root.
                                                                (r.Receptor.Instance.Enabled))); // .ContainsKey(protocol.DeclTypeName);
                }
            }

            return(ret);
        }
Exemple #11
0
        /// <summary>
        /// Internal carrier creation.  This includes the "stopRecursion" flag to prevent wildcard receptors from receiving ad-infinitum their own emissions.
        /// </summary>
        protected ICarrier CreateCarrier(IReceptorInstance from, ISemanticTypeStruct protocol, string protocolPath, dynamic signal, bool stopRecursion, bool isSystemMessage = false, ICarrier parentCarrier = null, bool emitSubElements = true)
        {
            Carrier carrier = null;

            if (from.GetEnabledEmittedProtocols().Any(p => p.Protocol == protocol.DeclTypeName) || isSystemMessage)
            {
                carrier = new Carrier(protocol, protocolPath, signal, parentCarrier);
                // ************ MOVED TO A: **************
                // The reason this was moved is so that we fire NewCarrier only for actual receptors with protocols enabled for that receptor.
                // TODO: However, this means that we no longer queue protocols for which we have no receptors.  Not sure if we actually want this particular feature.
                // NewCarrier.Fire(this, new NewCarrierEventArgs(from, carrier));

                // We pass along the stopRecursion flag to prevent wild-card carrier receptor from receiving their own emissions, which would result in a new carrier,
                // ad-infinitum.
                ProcessReceptors(from, carrier, stopRecursion);
            }

            // Recurse into SE's of the protocol and emit carriers for those as well, if a receiver exists.
            if (!isSystemMessage && emitSubElements)
            {
                // The carrier might be null if there's no receiver for the parent carrier.  In this case, we need to create a dummy carrier so we have a parent.
                if (carrier == null)
                {
                    carrier = new Carrier(protocol, protocolPath, signal, parentCarrier);
                }

                CreateCarriersForSemanticElements(from, protocol, protocol.DeclTypeName, signal, stopRecursion, carrier);
            }

            return(carrier);
        }
Exemple #12
0
		public Carrier(ISemanticTypeStruct protocol, string protocolPath, dynamic signal, ICarrier parentCarrier)
		{
			Protocol = protocol;
			Signal = signal;
			ProtocolPath = protocolPath;
			ParentCarrier = parentCarrier;
		}
Exemple #13
0
        protected bool ProcessSignal(ISemanticTypeStruct protocol, dynamic signal)
        {
            bool ret = false;

            currentProtocol = protocol.DeclTypeName;                            // Used in exception processing.
            // TODO: See ref 03282015 in Receptors.cs -- We probably don't need to run the Qualifier check here.
            ReceiveQualifier rq = receiveProtocols.Find(rp => rp.Protocol == protocol.DeclTypeName && rp.Qualifier(signal));

            if (rq == null)
            {
                ret = CheckSubTypes(protocol, signal);
            }
            else
            {
                try
                {
                    ret = true;
                    rq.Action(signal);
                }
                catch (Exception ex)
                {
                    EmitException(ex);
                }
            }

            return(ret);
        }
Exemple #14
0
        /// <summary>
        /// Create the table and column definitions for the protocol.
        /// </summary>
        protected void CreateViewerTable()
        {
            if (!String.IsNullOrEmpty(ProtocolName))
            {
                DataTable           dt = new DataTable();
                ISemanticTypeStruct st = rsys.SemanticTypeSystem.GetSemanticTypeStruct(ProtocolName);
                st.AllTypes.ForEach(t =>
                {
                    try
                    {
                        // TODO: MofN has two native types, which causes an error when getting the implementing type (can only have one native type.)
                        // What we need here is the ability to have sub-table of child native types for the current semantic type.
                        // Right now, we're just ignoring the problem.
                        DataColumn dc = new DataColumn(t.Name, t.GetImplementingType(rsys.SemanticTypeSystem));
                        dt.Columns.Add(dc);
                    }
                    catch (Exception ex)
                    {
                    }
                });

                dvSignals             = new DataView(dt);
                dgvSignals.DataSource = dvSignals;
            }
        }
Exemple #15
0
        // TODO: Duplicate code.
        protected void Say(string msg)
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("TextToSpeech");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("TextToSpeech");

            signal.Text = msg;
            rsys.CreateCarrier(this, protocol, signal);
        }
Exemple #16
0
        protected void NoFilenameProvided()
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("DebugMessage");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("DebugMessage");

            signal.Message = "Thumbnail Converter: No image filename was provided.";
            rsys.CreateCarrier(this, protocol, signal);
        }
Exemple #17
0
        protected void FileMissing(string fn)
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("DebugMessage");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("DebugMessage");

            signal.Message = "Thumbnail Converter: The image file " + fn + " is missing!";
            rsys.CreateCarrier(this, protocol, signal);
        }
Exemple #18
0
        protected void SayHello(object sender, EventArgs args)
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("DebugMessage");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("DebugMessage");

            signal.Message = "Hello World!";
            rsys.CreateCarrier(this, protocol, signal);
        }
        protected ICarrier CreateAPODRecordCarrier()
        {
            ISemanticTypeStruct protocol      = rsys.SemanticTypeSystem.GetSemanticTypeStruct("APOD");
            dynamic             record        = rsys.SemanticTypeSystem.Create("APOD");
            ICarrier            recordCarrier = rsys.CreateInternalCarrier(protocol, record);

            return(recordCarrier);
        }
        protected void EmitUrl(string url)
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("ScrapeWebpage");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("ScrapeWebpage");

            signal.URL.Value = url;
            rsys.CreateCarrier(this, protocol, signal);
        }
Exemple #21
0
        protected void CreateCarrierIfReceiver(string protocol, Action <dynamic> initializeSignal, bool emitSubElements = true)
        {
            ISemanticTypeStruct outprotocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct(protocol);
            dynamic             outsignal   = rsys.SemanticTypeSystem.Create(protocol);

            initializeSignal(outsignal);
            rsys.CreateCarrierIfReceiver(this, outprotocol, outsignal, null, emitSubElements);
        }
Exemple #22
0
 /// <summary>
 /// We want to stop the base class behavior here.
 /// </summary>
 protected override void ListenForProtocol()
 {
     if (!String.IsNullOrEmpty(ProtocolName))
     {
         ISemanticTypeStruct st = rsys.SemanticTypeSystem.GetSemanticTypeStruct(ProtocolName);
         st.SemanticElements.ForEach(se => AddEmitProtocol(se.Name));
     }
 }
        protected void EmitImageFile(string fn)
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("ImageFilename");
            dynamic             fsignal  = rsys.SemanticTypeSystem.Create("ImageFilename");

            fsignal.Filename = fn;
            rsys.CreateCarrierIfReceiver(this, protocol, fsignal);
        }
Exemple #24
0
        protected void CreateCarrier(string protocol, Action <dynamic> initializeSignal)
        {
            ISemanticTypeStruct outprotocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct(protocol);
            dynamic             outsignal   = rsys.SemanticTypeSystem.Create(protocol);

            initializeSignal(outsignal);
            rsys.CreateCarrier(this, outprotocol, outsignal);
        }
Exemple #25
0
        /// <summary>
        /// Recurse into the named structure, returning itself and all sub-structures.
        /// The return is a list of tuples, where Item1 is the ST and Item2 is the parent ST of Item1
        /// </summary>
        public List <Tuple <ISemanticTypeStruct, ISemanticTypeStruct> > GetAllSemanticTypes(string protocolName)
        {
            List <Tuple <ISemanticTypeStruct, ISemanticTypeStruct> > ret = new List <Tuple <ISemanticTypeStruct, ISemanticTypeStruct> >();
            ISemanticTypeStruct sts = GetSemanticTypeStruct(protocolName);

            GetAllSemanticTypes(sts, null, ret);

            return(ret);
        }
Exemple #26
0
        protected void Emit(string url, string html)
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("WebpageHtml");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("WebpageHtml");

            signal.URL  = url;
            signal.HTML = html;
            rsys.CreateCarrier(this, protocol, signal);
        }
Exemple #27
0
        /// <summary>
        /// Create a carrier of the specified protocol and signal.
        /// </summary>
        /// <param name="from">The source receptor.  Cay be null.</param>
        /// <param name="protocol">The protocol.</param>
        /// <param name="signal">The signal in the protocol's format.</param>
        public ICarrier CreateCarrier(IReceptorInstance from, ISemanticTypeStruct protocol, dynamic signal)
        {
            // This calls the internal method with recursion set to false.  We don't want to expose this
            // flag, so this method is a public front, as receptors should never set the "stop recursion" flag
            // to true when creating carriers.
            ICarrier carrier = CreateCarrier(from, protocol, signal, false);

            return(carrier);
        }
Exemple #28
0
        /// <summary>
        /// We require this table from the persistor.
        /// </summary>
        protected void RequireEventTable()
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("RequireTable");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("RequireTable");

            signal.TableName = "LastEventDateTime";
            signal.Schema    = "LastEventDateTime";
            rsys.CreateCarrier(this, protocol, signal);
        }
Exemple #29
0
        /// <summary>
        /// Creates the carrier for the timer event.
        /// </summary>
        protected void CreateEventCarrier()
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("TimerEvent");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("TimerEvent");

            signal.EventName     = EventName;
            signal.EventDateTime = (DateTime)LastEventTime;
            rsys.CreateCarrier(receptor, protocol, signal);
        }
Exemple #30
0
        /// <summary>
        /// Emit a semantic protocol with the value in the selected row and the column determined by the semantic element name.
        /// </summary>
        protected void OnCellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            ISemanticTypeStruct st = rsys.SemanticTypeSystem.GetSemanticTypeStruct(ProtocolName);

            st.SemanticElements.ForEach(se =>
            {
                CreateCarrier(se.Name, signal => se.SetValue(rsys.SemanticTypeSystem, signal, dvSignals[e.RowIndex][se.Name].ToString()));
            });
        }
Exemple #31
0
        protected void EmitError(string url, string error)
        {
            ISemanticTypeStruct protocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct("WebpageHtml");
            dynamic             signal   = rsys.SemanticTypeSystem.Create("WebpageHtml");

            signal.URL    = url;
            signal.Errors = error;
            rsys.CreateCarrier(this, protocol, signal);
        }
		/// <summary>
		/// Any reference to a child semantic element is implemented as a foreign key.
		/// Returns any foreign key creation sql statements in fkSql.
		/// </summary>
		protected void CreateFkSql(ISemanticTypeStruct sts, List<Tuple<string, Type>> fieldTypes, List<string> fkSql)
		{
			// Create FK's for child SE's.
			sts.SemanticElements.ForEach(child =>
			{
				string fkFieldName = "FK_" + child.Name + "ID";
				fieldTypes.Add(new Tuple<string, Type>(fkFieldName, typeof(long)));
				fkSql.Add(dbio.GetForeignKeySql(sts.DeclTypeName, fkFieldName, child.Name, "ID"));
			});
		}
Exemple #33
0
		protected bool ProcessSignal(ISemanticTypeStruct protocol, dynamic signal)
		{
			bool ret = false;
			currentProtocol = protocol.DeclTypeName;		// Used in exception processing.
			// TODO: See ref 03282015 in Receptors.cs -- We probably don't need to run the Qualifier check here.
			ReceiveQualifier rq = receiveProtocols.Find(rp => rp.Protocol == protocol.DeclTypeName && rp.Qualifier(signal));

			if (rq == null)
			{
				ret = CheckSubTypes(protocol, signal);
			}
			else
			{
				try
				{
					ret = true;
					rq.Action(signal);
				}
				catch (Exception ex)
				{
					EmitException(ex);
				}
			}

			return ret;
		}
Exemple #34
0
		/// <summary>
		/// Recurse into SE's of the protocol and emit carriers for those as well, if a receiver exists.
		/// </summary>
		protected void CreateCarriersForSemanticElements(IReceptorInstance from, ISemanticTypeStruct protocol, string protocolPath, dynamic signal, bool stopRecursion, ICarrier parentCarrier)
		{
			protocol.SemanticElements.ForEach(se =>
				{
					dynamic subsignal = SemanticTypeSystem.Clone(signal, se); // Clone the contents of the signal's semantic element into the subsignal.

					// We may have a null child, in which case, don't drill any further into the structure!
					if (subsignal != null)
					{
						ISemanticTypeStruct semStruct = SemanticTypeSystem.GetSemanticTypeStruct(se.Name);
						// Will result in recursive calls for all sub-semantic types.
						CreateCarrierIfReceiver(from, semStruct, protocolPath + "." + semStruct.DeclTypeName, subsignal, parentCarrier);
					}
				});
		}
		/// <summary>
		/// Creates the key and intializes the value instance if the key is missing from the semantic type foreign key map.
		/// </summary>
		protected void CreateKeyIfMissing(Dictionary<ISemanticTypeStruct, List<FKValue>> stfkMap, ISemanticTypeStruct sts)
		{
			if (!stfkMap.ContainsKey(sts))
			{
				stfkMap[sts] = new List<FKValue>();
			}
		}
		/// <summary>
		/// Create, if it doesn't exist, the custom type to handle the resulting joined results.
		/// </summary>
		protected object CreateCustomType(List<string> types, out ISemanticTypeStruct outprotocol)
		{
			string customTypeName = String.Join("_", types);

			if (!rsys.SemanticTypeSystem.VerifyProtocolExists(customTypeName))
			{
				rsys.SemanticTypeSystem.CreateCustomType(customTypeName, types);
				AddEmitProtocol(customTypeName);		// We now emit this custom protocol.
			}

			outprotocol = rsys.SemanticTypeSystem.GetSemanticTypeStruct(customTypeName);
			object outsignal = rsys.SemanticTypeSystem.Create(customTypeName);

			return outsignal;
		}
		/// <summary>
		/// Increment the use counter for the structure.
		/// </summary>
		protected int IncrementUseCount(ISemanticTypeStruct childsts, Dictionary<ISemanticTypeStruct, int> structureUseCounts)
		{
			int ret;

			if (!structureUseCounts.TryGetValue(childsts, out ret))
			{
				structureUseCounts[childsts] = 0;
			}

			ret = structureUseCounts[childsts] + 1;
			structureUseCounts[childsts] = ret;

			return ret;
		}
		/// <summary>
		/// Append the use counter if it exists.
		/// </summary>
		protected string GetUseName(ISemanticTypeStruct sts, Dictionary<ISemanticTypeStruct, int> structureUseCounts)
		{
			int count;
			string ret = sts.DeclTypeName;

			if (structureUseCounts.TryGetValue(sts, out count))
			{
				ret = ret + count;
			}

			return ret;
		}
		protected void EmitSignals(List<object> signals, ISemanticTypeStruct sts)
		{
			// Create a carrier for each of the signals in the returned record collection.
			if (UnitTesting)
			{
				signals.ForEach(s => rsys.CreateCarrier(this, sts, s));
			}
			else
			{
				signals.ForEach(s => rsys.CreateCarrierIfReceiver(this, sts, s));
			}
		}
		/// <summary>
		/// Build the query string to test for uniqueness from NT and SE (FK) unique fields.
		/// </summary>
		protected StringBuilder BuildUniqueQueryStatement(bool hasFKValues, List<FKValue> fkValues, ISemanticTypeStruct sts, List<IFullyQualifiedNativeType> uniqueFieldValues, bool allFKs)
		{
			// Get ST's to insert as FK_ID's:
			StringBuilder sb = new StringBuilder("select id from " + dbio.Delimited(sts.DeclTypeName) + " where ");

			// Put NT fields into "where" clause.
			sb.Append(String.Join(" and ", uniqueFieldValues.Select(f => dbio.Delimited(f.Name) + " = @" + f.Name)));

			// Put unique ST fields into "where" clause.
			if (hasFKValues && fkValues.Any(fk => fk.UniqueField || allFKs))
			{
				if (uniqueFieldValues.Count > 0) sb.Append(" and ");
				sb.Append(String.Join(" and ", fkValues.Where(fk => fk.UniqueField || allFKs).Select(fk => dbio.Delimited(fk.FieldName) + " = @" + fk.FieldName)));
			}

			return sb;
		}
		/// <summary>
		/// For each child that has a non-null signal, process its children.
		/// </summary>
		protected void ProcessChildren(Dictionary<ISemanticTypeStruct, List<FKValue>> stfkMap, ISemanticTypeStruct sts, object signal, bool childAsUnique)
		{
			sts.SemanticElements.ForEach(child =>
			{
				// Get the child signal and STS and check it, returning a new or existing ID for the entry.
				ISemanticTypeStruct childsts = child.Element.Struct; // rsys.SemanticTypeSystem.GetSemanticTypeStruct(child.Name);
				object childSignal = GetChildSignal(signal, child);

				// We don't insert null child signals.
				if (childSignal != null)
				{
					int id = ProcessSTS(stfkMap, childsts, childSignal, (sts.Unique || childAsUnique));
					RegisterForeignKeyID(stfkMap, sts, child, id);
				}
			});
		}
		protected int Insert(Dictionary<ISemanticTypeStruct, List<FKValue>> stfkMap, ISemanticTypeStruct sts, object signal)
		{
			// Get native types to insert:
			List<IFullyQualifiedNativeType> ntFieldValues = rsys.SemanticTypeSystem.GetFullyQualifiedNativeTypeValues(signal, sts.DeclTypeName, false);
			StringBuilder sb = new StringBuilder("insert into " + sts.DeclTypeName + " (");
			sb.Append(String.Join(", ", ntFieldValues.Select(f => f.Name)));

			// Get ST's to insert as FK_ID's:
			List<FKValue> fkValues;
			bool hasFKValues = stfkMap.TryGetValue(sts, out fkValues);

			if (hasFKValues && fkValues.Count > 0)
			{
				// Join in the FK_ID field names.
				if (ntFieldValues.Count > 0) sb.Append(", ");
				sb.Append(string.Join(", ", fkValues.Select(fkv => fkv.FieldName)));
			}

			// Setup NT field values:
			sb.Append(") values (");
			sb.Append(String.Join(", ", ntFieldValues.Select(f => "@" + f.Name)));

			// Setup ST FK parameters:
			if (hasFKValues && fkValues.Count > 0)
			{
				if (ntFieldValues.Count > 0) sb.Append(", ");
				sb.Append(string.Join(", ", fkValues.Select(fkv => "@" + fkv.FieldName)));
			}

			sb.Append(")");
			IDbCommand cmd = dbio.CreateCommand();

			// Assign NT values:
			ntFieldValues.ForEach(fv => cmd.Parameters.Add(dbio.CreateParameter(fv.Name, fv.Value)));

			// Assign FK values:
			if (hasFKValues && fkValues.Count > 0)
			{
				fkValues.ForEach(fkv => cmd.Parameters.Add(dbio.CreateParameter(fkv.FieldName, fkv.ID)));
			}

			cmd.CommandText = sb.ToString();
			LogSqlStatement(cmd.CommandText);
			cmd.ExecuteNonQuery();

			int id = dbio.GetLastID(sts.DeclTypeName);

			return id;
		}
Exemple #43
0
		/// <summary>
		/// Return the SE (possibly "this") that contains the specified SE.
		/// </summary>
		public ISemanticTypeStruct SemanticElementContaining(ISemanticTypeStruct stsToFind)
		{
			ISemanticTypeStruct sts = null;

			foreach (SemanticElement se in SemanticElements)
			{
				if (se.Element.Struct == stsToFind)
				{
					sts = se.Element.Struct;
					break;
				}

				// Recurse.
				sts = se.Element.Struct.SemanticElementContaining(stsToFind);

				if (sts != null)
				{
					break;
				}
			}

			return sts;
		}
		/// <summary>
		/// Insert the record if it doesn't exist.
		/// </summary>
		protected int InsertIfRecordDoesntExist(Dictionary<ISemanticTypeStruct, List<FKValue>> stfkMap, ISemanticTypeStruct sts, object signal, List<IFullyQualifiedNativeType> fieldValues, bool allFKs)
		{
			int id = -1;
			bool exists = QueryUniqueness(stfkMap, sts, signal, fieldValues, out id, allFKs);

			if (!exists)
			{
				id = Insert(stfkMap, sts, signal);
			}

			return id;
		}
		/// <summary>
		/// Drills into any child semantic elements, accumulating foreign keys for each level in the semantic hierarchy.
		/// When all children are inserted/updated, the parent can be inserted.
		/// </summary>
		protected int ProcessSTS(Dictionary<ISemanticTypeStruct, List<FKValue>> stfkMap, ISemanticTypeStruct sts, object signal, bool childAsUnique = false)
		{
			// Drill into each child ST and assign the return ID to this ST's FK for the child table name.
			ProcessChildren(stfkMap, sts, signal, childAsUnique);

			// Having processed all child ST's, We can now make the same determination of
			// whether the record needs to check for uniqueness, however at this level,
			// we need to write out both ST and any NT values in the current ST structure.
			// This is very similar to an ST without child ST's, but here we also use ST's that are designated as unique to build the composite key.
			int id = ArbitrateUniqueness(stfkMap, sts, signal, childAsUnique);

			return id;
		}
		/// <summary>
		/// Registers a foreign key name and value to be associated with the specified semantic structure, which is used when the ST is inserted
		/// after all child elements have been resolved.
		/// </summary>
		protected void RegisterForeignKeyID(Dictionary<ISemanticTypeStruct, List<FKValue>> stfkMap, ISemanticTypeStruct sts, ISemanticElement child, int id)
		{
			// Associate the ID to this ST's FK for that child table.
			string fieldName = "FK_" + child.Name + "ID";
			CreateKeyIfMissing(stfkMap, sts);
			stfkMap[sts].Add(new FKValue(fieldName, id, child.UniqueField));
		}
Exemple #47
0
		/// <summary>
		/// Create a carrier of the specified protocol and signal.
		/// </summary>
		/// <param name="from">The source receptor.  Cay be null.</param>
		/// <param name="protocol">The protocol.</param>
		/// <param name="signal">The signal in the protocol's format.</param>
		public ICarrier CreateCarrier(IReceptorInstance from, ISemanticTypeStruct protocol, dynamic signal, ICarrier parentCarrier = null, bool emitSubElements = true)
		{
			// This calls the internal method with recursion set to false.  We don't want to expose this 
			// flag, so this method is a public front, as receptors should never set the "stop recursion" flag
			// to true when creating carriers.
			// TODO: Improve these "is it a system message" tests -- figure out how to get rid of these hardcoded string.
			ICarrier carrier = CreateCarrier(from, protocol, protocol.DeclTypeName, signal, false, protocol.DeclTypeName=="SystemMessage" || from.Name=="DropReceptor", parentCarrier, emitSubElements);

			return carrier;
		}
		/// <summary>
		/// Based on whether a semantic element is unique or whether the foreign key fields or native types are unique, we determine how to determine uniqueness.
		/// We always perform an insert if there is no way to determine whether the record is unique.
		/// If it is unique, the ID of the existing record is returned.
		/// </summary>
		/// <param name="stfkMap"></param>
		protected int ArbitrateUniqueness(Dictionary<ISemanticTypeStruct, List<FKValue>> stfkMap, ISemanticTypeStruct sts, object signal, bool childAsUnique)
		{
			int id = -1;

			if (sts.Unique || childAsUnique)
			{
				// All FK's and NT's of this ST are considered part of the composite key.
				// Get all NT's specifically for this ST (no recursive drilldown)
				// False here indicates that we only want the native types for this ST -- we aren't recursing into child ST's.
				List<IFullyQualifiedNativeType> fieldValues = rsys.SemanticTypeSystem.GetFullyQualifiedNativeTypeValues(signal, sts.DeclTypeName, false);
				// True indicates that all FK's comprise the composite FK (in addition to unique NT's.)
				id = InsertIfRecordDoesntExist(stfkMap, sts, signal, fieldValues, true);
			}
			else if (sts.SemanticElements.Any(se => se.UniqueField) || sts.NativeTypes.Any(nt => nt.UniqueField))
			{
				// Get only unique NT's specifically for this ST (no recursive drilldown)
				// Note that a unique semantic element will automatically set the unique field for its native type children, subchildren, etc.
				// False here indicates that we only want the native types for this ST -- we aren't recursing into child ST's.
				List<IFullyQualifiedNativeType> fieldValues = rsys.SemanticTypeSystem.GetFullyQualifiedNativeTypeValues(signal, sts.DeclTypeName, false).Where(fqnt => fqnt.NativeType.UniqueField).ToList();
				// False indicates that only those FK's marked as unique comprise the composite FK (in addition to unique NT's.)
				id = InsertIfRecordDoesntExist(stfkMap, sts, signal, fieldValues, false);
			}
			else
			{
				// No SE's or NT's are unique, so just insert the ST, as we cannot make a determination regarding uniqueness.
				id = Insert(stfkMap, sts, signal);
			}

			return id;
		}
Exemple #49
0
		protected void CreateCarrierIfReceiver(IReceptorInstance from, ISemanticTypeStruct protocol, string protocolPath, dynamic signal, ICarrier parentCarrier, bool emitSubElements = true)
		{
			if (from.GetEnabledEmittedProtocols().Any(p => p.Protocol == protocol.DeclTypeName))
			{
				if (TargetReceptorExistsFor(ReceptorFromInstance(from), protocol, protocol.DeclTypeName == protocolPath))
				{
					// This call will recurse for us.
					// CreateCarrier(IReceptorInstance from, ISemanticTypeStruct protocol, string protocolPath, dynamic signal, bool stopRecursion, bool isSystemMessage = false, ICarrier parentCarrier = null)
					CreateCarrier(from, protocol, protocolPath, signal, false, false, parentCarrier, emitSubElements, protocol.DeclTypeName == protocolPath);
				}
				else
				{
					if (emitSubElements)
					{
						// Recurse into SE's of the protocol and emit carriers for those as well, if a receiver exists.
						// We do this even if there isn't a target for the top-level receptor.
						// However, we do create a Carrier instance as the parent so the child can reference it if necessary.
						Carrier carrier = new Carrier(protocol, protocolPath, signal, parentCarrier);
						CreateCarriersForSemanticElements(from, protocol, protocolPath, signal, false, carrier);
					}
				}
			}
			else
			{
				if (emitSubElements)
				{
					// Create a Carrier instance as the parent so the child can reference it if necessary.
					Carrier carrier = new Carrier(protocol, protocolPath, signal, parentCarrier);
					CreateCarriersForSemanticElements(from, protocol, protocolPath, signal, false, carrier);
				}
			}
		}
		/// <summary>
		/// The supported native types are simple field name - Type tuples.
		/// </summary>
		protected void CreateNativeTypes(ISemanticTypeStruct sts, List<Tuple<string, Type>> fieldTypes)
		{
			// Create fields for NT's.
			sts.NativeTypes.ForEach(child =>
				{
					Type t = child.GetImplementingType(rsys.SemanticTypeSystem);

					if (t != null)
					{
						fieldTypes.Add(new Tuple<string, Type>(child.Name, t));
					}
					else
					{
						// TODO: The reason for the try-catch is to deal with implementing types we don't support yet, like List<SomeType>
						// For now, we create a stub type.
						fieldTypes.Add(new Tuple<string, Type>(child.Name, typeof(string)));
					}
				});
		}
Exemple #51
0
		/// <summary>
		/// Create a carrier of the specified protocol and signal if a receiver currently exists.
		/// Note that because a carrier might not be created, there is no return value for this method.
		/// </summary>
		/// <param name="from">The source receptor.  Cay be null.</param>
		/// <param name="protocol">The protocol.</param>
		/// <param name="signal">The signal in the protocol's format.</param>
		public void CreateCarrierIfReceiver(IReceptorInstance from, ISemanticTypeStruct protocol, dynamic signal, ICarrier parentCarrier = null, bool emitSubElements = true)
		{
			CreateCarrierIfReceiver(from, protocol, protocol.DeclTypeName, signal, parentCarrier, emitSubElements);
		}
		/// <summary>
		/// Recurses the semantic structure to generate the native type fields and the semantic element joins.
		/// fqntAliases -- fully qualified native type and it's actual alias in the field list.
		/// </summary>
		protected void BuildQuery(ISemanticTypeStruct sts, List<string> fields, List<string> joins, Dictionary<ISemanticTypeStruct, int> structureUseCounts, string fqn, List<Tuple<string, string>> fqntAliases)
		{
			// Add native type fields.
			string parentName = GetUseName(sts, structureUseCounts);
			sts.NativeTypes.ForEach(nt =>
				{
					string qualifiedFieldName = fqn + "." + nt.Name;
					string qualifiedAliasFieldName = parentName + "." + nt.Name;
					fields.Add(qualifiedAliasFieldName);
					fqntAliases.Add(new Tuple<string, string>(qualifiedFieldName, qualifiedAliasFieldName));
				});

			sts.SemanticElements.ForEach(child =>
				{
					ISemanticTypeStruct childsts = child.Element.Struct; // rsys.SemanticTypeSystem.GetSemanticTypeStruct(child.Name);
					IncrementUseCount(childsts, structureUseCounts);
					string asChildName = GetUseName(childsts, structureUseCounts);
					joins.Add("left join " + childsts.DeclTypeName + " as " + asChildName + " on " + asChildName + ".ID = " + parentName + ".FK_" + childsts.DeclTypeName + "ID");
					BuildQuery(childsts, fields, joins, structureUseCounts, fqn+"."+childsts.DeclTypeName, fqntAliases);
				});
		}
Exemple #53
0
		/// <summary>
		/// Internal carrier creation.  This includes the "stopRecursion" flag to prevent wildcard receptors from receiving ad-infinitum their own emissions.
		/// </summary>
		protected ICarrier CreateCarrier(IReceptorInstance from, ISemanticTypeStruct protocol, string protocolPath, dynamic signal, bool stopRecursion, bool isSystemMessage = false, ICarrier parentCarrier = null, bool emitSubElements = true, bool isRoot = true)
		{
			Carrier carrier = null;

			if (from.GetEnabledEmittedProtocols().Any(p => p.Protocol == protocol.DeclTypeName) || isSystemMessage)
			{
				carrier = new Carrier(protocol, protocolPath, signal, parentCarrier);
				// ************ MOVED TO A: **************
				// The reason this was moved is so that we fire NewCarrier only for actual receptors with protocols enabled for that receptor.
				// TODO: However, this means that we no longer queue protocols for which we have no receptors.  Not sure if we actually want this particular feature.
				// NewCarrier.Fire(this, new NewCarrierEventArgs(from, carrier));

				// We pass along the stopRecursion flag to prevent wild-card carrier receptor from receiving their own emissions, which would result in a new carrier,
				// ad-infinitum.
				ProcessReceptors(from, carrier, stopRecursion, isRoot);
			}

			// Recurse into SE's of the protocol and emit carriers for those as well, if a receiver exists.
			if (!isSystemMessage && emitSubElements)
			{
				// The carrier might be null if there's no receiver for the parent carrier.  In this case, we need to create a dummy carrier so we have a parent.
				if (carrier == null)
				{
					carrier = new Carrier(protocol, protocolPath, signal, parentCarrier);
				}

				CreateCarriersForSemanticElements(from, protocol, protocol.DeclTypeName, signal, stopRecursion, carrier);
			}

			return carrier;
		}
		protected string CreateSqlStatement(object signal, ISemanticTypeStruct sts, List<string> fields, List<string> joins, List<Tuple<string, string>> fqntAliases, string where, List<string> orderBy, string maxRecords, out Dictionary<string, object> parameters)
		{
			// CRLF for pretty inspection.
			string sqlQuery = "select " + String.Join(", ", fields) + " \r\nfrom " + sts.DeclTypeName + " \r\n" + String.Join(" \r\n", joins);
			parameters = new Dictionary<string, object>();
			sqlQuery = sqlQuery + " " + ParseWhereClause(signal, where, fqntAliases, parameters);
			sqlQuery = sqlQuery + " " + ParseOrderBy(orderBy, fqntAliases);
			sqlQuery = dbio.AddLimitClause(sqlQuery, maxRecords);

			return sqlQuery;
		}
Exemple #55
0
		/// <summary>
		/// Returns true if there is an enabled target from the specified receptor with the specified protocol.
		/// </summary>
		protected bool TargetReceptorExistsFor(IReceptor from, ISemanticTypeStruct protocol, bool isRoot)
		{
			bool ret = false;

			// Some bullet proofing that was revealed in unit testing.
			if (from != null)
			{
				List<IReceptorConnection> targets = new List<IReceptorConnection>();
				if (MasterReceptorConnectionList.TryGetValue(from, out targets))
				{
					// This annoying piece of code assumes that a receptor will have only one connection between "from" to "to".
					// In the case of the semantic database, a "from" receptor can have multiple connections with the same semantic database receptor.
					// In other words, the returned list consists of [n] identical instances, where [n] is the number of different protocols from "from" to the target receptor.
					// To fix this problem, we get only the distinct instances.
					targets = targets.Distinct().ToList();
					// We're only interested in enabled receptors, and we ignore ourselves.
					ret = targets.Any(r => r.Receptor != from && 
						r.Receptor.Instance.Enabled && 
						r.PermeabilityProtocol == protocol.DeclTypeName &&
						(!r.RootOnly || isRoot)); // &&			// root protocol or we don't care if it's not the root.
						// r.Receptor.Instance.GetEnabledReceiveProtocols().Select(rp => rp.Protocol).Contains(protocol.DeclTypeName));
				}

				if (!ret)
				{
					// check protocol map for receivers that are not the issuing receptor, ignoring ourselves.
					ret = protocolReceptorMap.Any(kvp => (kvp.Key == protocol.DeclTypeName) && 
						kvp.Value.Any(r => (r.Receptor != from) &&
							r.PermeabilityProtocol == protocol.DeclTypeName &&
							(!r.RootOnly || isRoot) &&			// root protocol or we don't care if it's not the root.
							(r.Receptor.Instance.Enabled))); // .ContainsKey(protocol.DeclTypeName);
				}
			}

			return ret;
		}
		protected List<object> PopulateSignals(string sqlQuery, ISemanticTypeStruct sts, Dictionary<string, object> parameters)
		{
			List<object> ret = new List<object>();
			IDataReader reader = AcquireReader(sqlQuery, parameters);

			while (reader.Read())
			{
				object outsignal = rsys.SemanticTypeSystem.Create(sts.DeclTypeName);
				int counter = 0;		// For a single table join, counter is always 0.
				// Populate the signal with the columns in each record read.
				Populate(sts, outsignal, reader, ref counter);
				ret.Add(outsignal);
			}

			reader.Close();

			return ret;
		}
Exemple #57
0
		protected bool CheckSubTypes(ISemanticTypeStruct protocol, dynamic signal)
		{
			bool ret = false;

			foreach(ISemanticElement se in protocol.SemanticElements)
			{
				dynamic subsignal = rsys.SemanticTypeSystem.Clone(signal, se); // Clone the contents of the signal's semantic element into the subsignal.

				if (subsignal != null)
				{
					ret = ProcessSignal(se.Element.Struct, subsignal);

					if (ret)
					{
						break;
					}
				}
			};

			return ret;
		}
		protected void FixupBaseType(Dictionary<string, List<Tuple<ISemanticTypeStruct, ISemanticTypeStruct>>> stSemanticTypes, ISemanticTypeStruct sharedStruct, List<TypeIntersection> joinOrder, int joinIdx, ref string baseType, ref ISemanticTypeStruct parent0, ref bool parent0ElementUnique)
		{
			// If we've changed the "base" type, then update parent0 and parent0ElementUnique.
			if (joinOrder[joinIdx].BaseType != baseType)
			{
				baseType = joinOrder[joinIdx].BaseType;
				parent0 = stSemanticTypes[baseType].First(t => t.Item1 == sharedStruct).Item2;
				parent0ElementUnique = parent0.SemanticElements.Any(se => se.Name == sharedStruct.DeclTypeName && se.UniqueField);
			}
		}
		/// <summary>
		/// Build and execute a select statement that determines if the record, based on a composite key, already exists.
		/// If so, return the ID of the record.
		/// </summary>
		protected bool QueryUniqueness(Dictionary<ISemanticTypeStruct, List<FKValue>> stfkMap, ISemanticTypeStruct sts, object signal, List<IFullyQualifiedNativeType> uniqueFieldValues, out int id, bool allFKs = false)
		{
			id = -1;
			bool ret = false;
			List<FKValue> fkValues;
			bool hasFKValues = stfkMap.TryGetValue(sts, out fkValues);
			StringBuilder sb = BuildUniqueQueryStatement(hasFKValues, fkValues, sts, uniqueFieldValues, allFKs); 
			IDbCommand cmd = AddParametersToCommand(uniqueFieldValues, hasFKValues, fkValues, allFKs);
			cmd.CommandText = sb.ToString();
			LogSqlStatement(cmd.CommandText);
			
			object oid = cmd.ExecuteScalar();
			ret = (oid != null);

			if (ret)
			{
				id = Convert.ToInt32(oid);
			}

			return ret;
		}
		/// <summary>
		/// Recursively populates the values into the signal.  The recursion algorithm here must match exactly the same
		/// form as the recursion algorithm in BuildQuery, as the correlation between field names and their occurrance
		/// in the semantic structure is relied upon.  For now at least.
		/// Returns true if there are any non-null NT valus.
		/// </summary>
		protected bool Populate(ISemanticTypeStruct sts, object signal, IDataReader reader, ref int parmNumber)
		{
			bool anyNonNull = false;
			List<object> vals = new List<object>();

			for (int i = 0; i < sts.NativeTypes.Count; i++)
			{
				vals.Add(reader[parmNumber++]);
			}

			// No NT's (vals.Count==0) means we just have an ST child, so continue on.
			// We have NT's.  Are they all null?
			//if ( (vals.Count > 0) && (vals.All(v => v == DBNull.Value)) )
			//{
			//	// We don't have a records populate for this query.
			//	ret = null;
			//}
			//else
			{
				// Add native type fields.  Use a foreach loop because ref types can't be used in lambda expressions.
				sts.NativeTypes.ForEachWithIndex((nt, idx) =>
				{
					object val = vals[idx];

					if (val != DBNull.Value)
					{
						Assert.TryCatch(() => nt.SetValue(rsys.SemanticTypeSystem, signal, val), (ex) => EmitException(ex));
						anyNonNull = true;
					}
					else
					{
						// throw new Exception("DBNull is an unsupported native value type.");
						// At the moment, we do nothing because we don't support null field values.
					}
				});

				foreach (ISemanticElement child in sts.SemanticElements)
				{
					ISemanticTypeStruct childsts = child.Element.Struct;
					object childSignal = GetChildSignal(signal, child);
					anyNonNull |= Populate(childsts, childSignal, reader, ref parmNumber);
				}
			}

			return anyNonNull;
		}