public void TestConditionMapAdd() { ConditionMap cmap = new ConditionMap(); ConditionKeyMap ckmap1 = new ConditionKeyMap("s3:prefix", "hello"); ConditionKeyMap ckmap2 = new ConditionKeyMap("s3:prefix", new HashSet <string> { "hello", "world" }); var testCases = new List <KeyValuePair <Tuple <string, ConditionKeyMap>, string> >() { // Add new key and value new KeyValuePair <Tuple <string, ConditionKeyMap>, string> (Tuple.Create <string, ConditionKeyMap>("StringEquals", ckmap1), @"{""StringEquals"":{""s3:prefix"":[""hello""]}}"), //Add existing key and value new KeyValuePair <Tuple <string, ConditionKeyMap>, string> (Tuple.Create <string, ConditionKeyMap>("StringEquals", ckmap1), @"{""StringEquals"":{""s3:prefix"":[""hello""]}}"), //Add existing key and new value new KeyValuePair <Tuple <string, ConditionKeyMap>, string> (Tuple.Create <string, ConditionKeyMap>("StringEquals", ckmap2), @"{""StringEquals"":{""s3:prefix"":[""hello"",""world""]}}"), }; int index = 0; foreach (KeyValuePair <Tuple <string, ConditionKeyMap>, string> pair in testCases) { Tuple <string, ConditionKeyMap> tuple = pair.Key; string expectedJSON = pair.Value; index += 1; cmap.Put(tuple.Item1, tuple.Item2); string cmapJSON = JsonConvert.SerializeObject(cmap, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); Assert.AreEqual(expectedJSON, cmapJSON); } }
/// <summary> /// Uses <see cref="ConditionMap"/> to find the boundary value as /// described in <see cref="IBoundaryConditionMap.GetBoundaryState"/> /// </summary> /// <param name="EdgeTag"> /// <see cref="IBoundaryConditionMap.GetBoundaryState"/> /// </param> /// <param name="time"> /// <see cref="IBoundaryConditionMap.GetBoundaryState"/> /// </param> /// <param name="x"> /// <see cref="IBoundaryConditionMap.GetBoundaryState"/> /// </param> /// <param name="normal"> /// <see cref="IBoundaryConditionMap.GetBoundaryState"/> /// </param> /// <param name="stateVector"> /// <see cref="IBoundaryConditionMap.GetBoundaryState"/> /// </param> /// <returns> /// <see cref="IBoundaryConditionMap.GetBoundaryState"/> /// </returns> public StateVector GetBoundaryState(byte EdgeTag, double time, double[] x, double[] normal, StateVector stateVector) { string edgeTagName = EdgeTagNames[EdgeTag]; if (!ConditionMap.ContainsKey(edgeTagName)) { throw new ArgumentException("No boundary condition found for edge \"" + edgeTagName + "\"", "EdgeTag"); } return(ConditionMap[edgeTagName].GetBoundaryState(time, x, normal, stateVector)); }
/// <summary> /// Force a refresh for all active conditions and inactive, unacknowledged conditions whose event notifications match the filter of the event subscription. /// </summary> /// <param name="dwConnection">The OLE Connection number returned from IConnectionPoint::Advise. This is passed to help the server determine which OPC event sink to call when the request completes.</param> public void Refresh(int dwConnection) { try { if (m_RefreshID != 0 || m_RefreshQ.Count != 0) { throw ComUtils.CreateComException("Refresh", ResultIds.E_BUSY); } m_RefreshID = dwConnection; // Foe each source walk through all associated conditions. If the condition is "refreshable", i.e. Active or // inactive/unacknowledged, then create an event and push it on to the subscription's refresh queue SourceMap sourceMap = SourceMap.TheSourceMap; foreach (KeyValuePair <string, ConditionMap> kvp in sourceMap) { string sourceName = kvp.Key; ConditionMap conditionMap = kvp.Value; foreach (KeyValuePair <string, OPCCondition> kvpCond in conditionMap) { string conditionName = kvpCond.Key; OPCCondition cond = kvpCond.Value; if (cond.IsEnabled() && (cond.IsActive() || !cond.IsAcked())) { OnEventClass OEClass = new OnEventClass(sourceName, conditionName, cond); if (MatchesFilter(OEClass)) { m_RefreshQ.Enqueue(OEClass); } } } } if (m_RefreshQ.Count > 0) { ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork), null); } else { CancelRefresh(dwConnection); } } catch (Exception e) { Utils.Trace(e, "Unexpected error in Refresh"); throw ComUtils.CreateComException(e); } }
/// <summary> /// If the event type is CONDITION_EVENT then update any existing record of the condition and adjust /// state and change mask. /// </summary> /// <param name="EventNotification"></param> /// <param name="areas"></param> public void ProcessEventNotificationList(EventNotification EventNotification, string[] areas) { SourceMap sourceMap = SourceMap.TheSourceMap; try { lock (sourceMap) { OPCCondition cond; if (EventNotification.EventType == OpcRcw.Ae.Constants.CONDITION_EVENT) { ConditionMap conditionMap; if (sourceMap.TryGetValue(EventNotification.SourceID, out conditionMap) == false) { conditionMap = new ConditionMap(); sourceMap.Add(EventNotification.SourceID, conditionMap); } if (conditionMap.TryGetValue(EventNotification.ConditionName, out cond) == false) { cond = new OPCCondition(); cond.EventType = EventNotification.EventType; conditionMap.Add(EventNotification.ConditionName, cond); } ProcessCondition(EventNotification, areas, cond); // When the condition has transitioned to Acked (if ack required) and inactive or disabled // then remove it from the condition source/condition database if ((!cond.IsActive() || !cond.IsEnabled()) && (cond.IsAcked() || !cond.AckRequired)) { conditionMap.Remove(EventNotification.ConditionName); } } else // a tracking or simple event { cond = new OPCCondition(); cond.EventType = EventNotification.EventType; ProcessCondition(EventNotification, areas, cond); } } } catch (Exception e) { Utils.Trace(e, "Unexpected error in ProcessEventNotificationList"); } }
/// <summary> /// If the event type is CONDITION_EVENT then update any existing record of the condition and adjust /// state and change mask. /// </summary> /// <param name="EventNotification"></param> /// <param name="areas"></param> public void ProcessEventNotificationList(EventNotification EventNotification, string[] areas) { SourceMap sourceMap = SourceMap.TheSourceMap; try { lock (sourceMap) { OPCCondition cond; if (EventNotification.EventType == OpcRcw.Ae.Constants.CONDITION_EVENT) { ConditionMap conditionMap; if (sourceMap.TryGetValue(EventNotification.SourceID, out conditionMap) == false) { conditionMap = new ConditionMap(); sourceMap.Add(EventNotification.SourceID, conditionMap); } if (conditionMap.TryGetValue(EventNotification.ConditionName, out cond) == false) { cond = new OPCCondition(); cond.EventType = EventNotification.EventType; conditionMap.Add(EventNotification.ConditionName, cond); } ProcessCondition(EventNotification, areas, cond); // When the condition has transitioned to Acked (if ack required) and inactive or disabled // then remove it from the condition source/condition database if ((!cond.IsActive() || !cond.IsEnabled()) && (cond.IsAcked() || !cond.AckRequired)) conditionMap.Remove(EventNotification.ConditionName); } else // a tracking or simple event { cond = new OPCCondition(); cond.EventType = EventNotification.EventType; ProcessCondition(EventNotification, areas, cond); } } } catch (Exception e) { Utils.Trace(e, "Unexpected error in ProcessEventNotificationList"); } }
/// <summary> /// Replaces the condition current stored against the given ID with a new one. /// </summary> /// <param name="conditionToReplace">The ID of the condition that should be replaced.</param> /// <param name="newCondition">The new condition.</param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="conditionToReplace"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="newCondition"/> is <see langword="null" />. /// </exception> /// <exception cref="UnknownScheduleConditionException"> /// Thrown if <paramref name="conditionToReplace"/> is not linked to a known condition. /// </exception> public void Update( ScheduleElementId conditionToReplace, IScheduleCondition newCondition) { { Lokad.Enforce.Argument(() => conditionToReplace); Lokad.Enforce.Argument(() => newCondition); Lokad.Enforce.With <UnknownScheduleConditionException>( m_Conditions.ContainsKey(conditionToReplace), Resources.Exceptions_Messages_UnknownScheduleCondition); } var oldInfo = m_Conditions[conditionToReplace].Information; var info = new ScheduleConditionInformation( conditionToReplace, oldInfo.Name, oldInfo.Description); m_Conditions[conditionToReplace] = new ConditionMap(info, newCondition); }
/// <summary> /// Replaces the condition current stored against the given ID with a new one. /// </summary> /// <param name="conditionToReplace">The ID of the condition that should be replaced.</param> /// <param name="newCondition">The new condition.</param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="conditionToReplace"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="newCondition"/> is <see langword="null" />. /// </exception> /// <exception cref="UnknownScheduleConditionException"> /// Thrown if <paramref name="conditionToReplace"/> is not linked to a known condition. /// </exception> public void Update( ScheduleElementId conditionToReplace, IScheduleCondition newCondition) { { Lokad.Enforce.Argument(() => conditionToReplace); Lokad.Enforce.Argument(() => newCondition); Lokad.Enforce.With<UnknownScheduleConditionException>( m_Conditions.ContainsKey(conditionToReplace), Resources.Exceptions_Messages_UnknownScheduleCondition); } var oldInfo = m_Conditions[conditionToReplace].Information; var info = new ScheduleConditionInformation( conditionToReplace, oldInfo.Name, oldInfo.Description); m_Conditions[conditionToReplace] = new ConditionMap(info, newCondition); }
// Tests if condition key map merges existing values public void TestConditionMapPutAll() { ConditionMap cmap1 = new ConditionMap(); cmap1.Add("StringEquals", new ConditionKeyMap("s3:prefix", new HashSet <string>() { "hello" })); ConditionMap cmap2 = new ConditionMap(); cmap2.Add("StringEquals", new ConditionKeyMap("s3:prefix", new HashSet <string>() { "world" })); ConditionMap cmap3 = new ConditionMap(); cmap3.Add("StringEquals", new ConditionKeyMap("s3:myprefix", new HashSet <string>() { "world" })); ConditionMap cmap4 = new ConditionMap(); cmap4.Add("StringEquals", new ConditionKeyMap("s3:prefix", new HashSet <string>() { "hello" })); var testCases = new List <KeyValuePair <Tuple <ConditionMap, ConditionMap>, string> >() { // Both args are empty new KeyValuePair <Tuple <ConditionMap, ConditionMap>, string>(Tuple.Create(new ConditionMap(), new ConditionMap()), @"{}"), // First arg empty new KeyValuePair <Tuple <ConditionMap, ConditionMap>, string>(Tuple.Create(new ConditionMap(), cmap1), @"{""StringEquals"":{""s3:prefix"":[""hello""]}}"), //Second arg empty new KeyValuePair <Tuple <ConditionMap, ConditionMap>, string>(Tuple.Create(cmap1, new ConditionMap()), @"{""StringEquals"":{""s3:prefix"":[""hello""]}}"), //Both args have same value new KeyValuePair <Tuple <ConditionMap, ConditionMap>, string>(Tuple.Create(cmap1, cmap4), @"{""StringEquals"":{""s3:prefix"":[""hello""]}}"), //Value of second arg will be merged new KeyValuePair <Tuple <ConditionMap, ConditionMap>, string>(Tuple.Create(cmap1, cmap2), @"{""StringEquals"":{""s3:prefix"":[""hello"",""world""]}}"), //second arg will be added new KeyValuePair <Tuple <ConditionMap, ConditionMap>, string>(Tuple.Create(cmap1, cmap3), @"{""StringEquals"":{""s3:prefix"":[""hello"",""world""],""s3:myprefix"":[""world""]}}"), }; int index = 0; foreach (KeyValuePair <Tuple <ConditionMap, ConditionMap>, string> pair in testCases) { try { index += 1; var testcase = pair.Key; ConditionMap first = testcase.Item1; ConditionMap second = testcase.Item2; string expectedConditionKMapJSON = pair.Value; first.PutAll(second); string cmpstring = JsonConvert.SerializeObject(first, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); Assert.AreEqual(cmpstring, expectedConditionKMapJSON); } catch (ArgumentException) { Assert.Fail(); } } }