/// <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); }
// TODO: This code needs to be optimized. /// <summary> /// Returns the target receptors that will receive the carrier protocol, qualified by the receptor's optional condition on the signal. /// </summary> protected List <IReceptorConnection> GetTargetReceptorsFor(IReceptor from, ICarrier carrier) { // Lastly, filter the list by qualified receptors that are not the source of the carrier. List <IReceptorConnection> newTargets = new List <IReceptorConnection>(); // From can be null if we're changing the layout during the time when carriers are being processed, // specifically, when a receptor is moved into or out of a membrane or the receptor is taken off the surface. if (from != null) { List <IReceptorConnection> targets; ISemanticTypeStruct protocol = carrier.Protocol; // 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. if (!MasterReceptorConnectionList.TryGetValue(from, out targets)) { // When the try fails, it sets targets to null. targets = new List <IReceptorConnection>(); } // To fix the aformentioned problem, we get only the distinct instances. targets = targets.Distinct().ToList(); // Only enabled receptors and receptors that are not the source of the carrier and our not ourselves. List <IReceptorConnection> filteredTargets = targets.Where(r => r.Receptor != from && r.Receptor.Instance.Enabled && r.Receptor.Instance.GetEnabledReceiveProtocols().Select(rq => rq.Protocol).Contains(protocol.DeclTypeName)).ToList(); // Will have a count of 0 if the receptor is the system receptor, ie, carrier animations or other protocols. // TODO: This seems kludgy, is there a better way of working with this? // Also, if the emitting receptor doesn't declare its protocol, this count will be 0, leading to potentially strange results. // For example, comment out the persistence receptors "IDReturn" and run the feed reader example. You'll see that TWO items // are returned as matching "RSSFeed" table name and for reasons unknown at the moment, protocolReceptorMap has two entries that qualify. if (filteredTargets.Count == 0) { // When the try fails, it sets targets to null. if (protocolReceptorMap.TryGetValue(protocol.DeclTypeName, out targets)) { filteredTargets = targets.Where(r => r.Receptor.Instance.Enabled && (r.Receptor != from) && true).ToList(); // Remove disabled receive protocols. filteredTargets = filteredTargets.Where(r => r.Receptor.Instance.GetReceiveProtocols().Exists(p => p.Protocol == protocol.DeclTypeName && p.Enabled)).ToList(); } } filteredTargets.Where(r => r.Receptor != from && r.Receptor.Instance.Enabled).ForEach(t => { // Get the list of receive actions and filters for the specific protocol. var receiveList = t.Receptor.Instance.GetEnabledReceiveProtocols().Where(rp => rp.Protocol == protocol.DeclTypeName); receiveList.ForEach(r => { // If qualified, add to the final target list. if (r.Qualifier(carrier.Signal)) { newTargets.Add(t); } }); }); // filteredTargets = filteredTargets.Where(t => t.Instance.GetReceiveProtocols().Any(rp => (rp.Protocol == protocol.DeclTypeName) && rp.Qualifier(carrier.Signal))).ToList(); // Get the targets of the single receive protocol that matches the DeclTypeName and whose qualifier returns true. // filteredTargets = filteredTargets.Where(t => t.Instance.GetReceiveProtocols().Single(rp => rp.Protocol == protocol.DeclTypeName).Qualifier(carrier.Signal)).ToList(); } else { // TODO: Should we log this error so we can further inspect the effects that it may have on processing carriers? } return(newTargets); }