public void PredicationEngine_Deleted() { Test(() => { var testNode = new SystemFolder(Repository.Root) { Name = "TestRoot" }; testNode.Save(); testNode.ForceDelete(); var testContent = testNode.Content ?? Content.Create(testNode); var prE = new PredicationEngine(testContent); Assert.IsTrue(prE.IsTrue("Name:TestRoot")); }); }
/// <inheritdoc/> public IEnumerable <WebHookSubscriptionInfo> GetRelevantSubscriptions(ISnEvent snEvent) { //TODO: implement a subscription cache that is invalidated when a subscription changes // Do NOT cache nodes, their data is already cached. Cache only ids, paths, or trees. List <WebHookSubscriptionInfo> allSubs; // load subscriptions in elevated mode because this is a system feature using (new SystemAccount()) { // ReSharper disable once RedundantBoolCompare allSubs = Content.All.DisableAutofilters().Where(c => c.InTree("/Root/System/WebHooks") && c.ContentHandler is WebHookSubscription && (bool)c["Enabled"] == true) .AsEnumerable() .Select(c => (WebHookSubscription)c.ContentHandler) .SelectMany(sub => { // prefilter: check if this event is relevant for the subscription var eventTypes = sub.GetRelevantEventTypes(snEvent); // handle multiple relevant event types by adding the subscription multiple times return(eventTypes.Select(et => new WebHookSubscriptionInfo(sub, et))); }) .Where(si => si != null && si.Subscription.IsValid) .ToList(); } if (!allSubs.Any()) { return(Array.Empty <WebHookSubscriptionInfo>()); } // use the already constructed Content instance if possible var content = snEvent.NodeEventArgs.SourceNode is GenericContent gc ? gc.Content : Content.Create(snEvent.NodeEventArgs.SourceNode); // filter by the query defined by the subscriber var pe = new PredicationEngine(content); return(allSubs.Where(sub => pe.IsTrue(sub.Subscription.FilterQuery)).ToList()); }
public void PredicationEngine_TypeIs() { Test(() => { var root = new SystemFolder(Repository.Root) { Name = "TestRoot" }; root.Save(); // CASE 1 var prE = new PredicationEngine(Content.Load("/Root/TestRoot")); Assert.IsTrue(prE.IsTrue("+TypeIs:SystemFolder")); Assert.IsTrue(prE.IsTrue("+TypeIs:Folder")); Assert.IsTrue(prE.IsTrue("+TypeIs:GenericContent")); // CASE 2 prE = new PredicationEngine(Content.Load("/Root/Content")); Assert.IsTrue(prE.IsTrue("+TypeIs:Workspace")); Assert.IsTrue(prE.IsTrue("+TypeIs:Folder")); Assert.IsTrue(prE.IsTrue("+TypeIs:GenericContent")); }); }
public void PredicationEngine_Errors() { void AssertError(PredicationEngine prE, string predication, Type exceptionType) { try { prE.IsTrue(predication); Assert.Fail($"{exceptionType.Namespace} was not thrown."); } catch (Exception e) { if (e.GetType() != exceptionType) { Assert.Fail($"{e.GetType().Name} was thrown. Expected: {exceptionType.Name}."); } } } Test(() => { ContentTypeInstaller.InstallContentType(CTD); var root = new SystemFolder(Repository.Root) { Name = "TestRoot" }; root.Save(); var content = Content.CreateNew("PredicationEngineTestNode", root, "PredicationEngineTestNode1"); content.Index = 42; content["Currency1"] = 42.42; content["DateTime1"] = new DateTime(1234, 5, 6); content.Save(); var prE = new PredicationEngine(content); // equality AssertError(prE, "Name:a?b", typeof(NotSupportedException)); // The '?' wildcard is not allowed AssertError(prE, "Name:*", typeof(NotSupportedException)); // The only one '*' is not allowed; }); }
public void PredicationEngine_InTree() { Test(() => { ContentTypeInstaller.InstallContentType(CTD); var root = new SystemFolder(Repository.Root) { Name = "TestRoot" }; root.Save(); var content = Content.CreateNew("PredicationEngineTestNode", root, "TestNode1"); content.Index = 42; content["DateTime1"] = new DateTime(1234, 5, 6); content["Currency1"] = 42.42; content.Save(); // CASE 1 var prE = new PredicationEngine(Content.Load("/Root/TestRoot/TestNode1")); Assert.IsTrue(prE.IsTrue("+InTree:/Root/TestRoot/TestNode1")); Assert.IsFalse(prE.IsTrue("+InTree:/Root/Content")); Assert.IsTrue(prE.IsTrue("+InTree:/Root/TestRoot")); Assert.IsTrue(prE.IsTrue("+InTree:/Root")); // CASE 2 prE = new PredicationEngine(Content.Load("/Root/TestRoot")); Assert.IsFalse(prE.IsTrue("+InTree:/Root/TestRoot/TestNode1")); Assert.IsFalse(prE.IsTrue("+InTree:/Root/Content")); Assert.IsTrue(prE.IsTrue("+InTree:/Root/TestRoot")); Assert.IsTrue(prE.IsTrue("+InTree:/Root")); // CASE 3 prE = new PredicationEngine(Content.Load("/Root")); Assert.IsFalse(prE.IsTrue("+InTree:/Root/TestRoot/TestNode1")); Assert.IsFalse(prE.IsTrue("+InTree:/Root/Content")); Assert.IsFalse(prE.IsTrue("+InTree:/Root/TestRoot")); Assert.IsTrue(prE.IsTrue("+InTree:/Root")); }); }
public IEnumerable <WebHookSubscriptionInfo> GetRelevantSubscriptions(ISnEvent snEvent) { var node = snEvent.NodeEventArgs.SourceNode; if (node == null) { return(Array.Empty <WebHookSubscriptionInfo>()); } var pe = new PredicationEngine(Content.Create(node)); // filter the hardcoded subscription list: return the ones that // match the current content return(Subscriptions.SelectMany(sub => { var eventTypes = sub.GetRelevantEventTypes(snEvent); // handle multiple relevant event types by adding the subscription multiple times return eventTypes.Select(et => new WebHookSubscriptionInfo(sub, et)); }).Where(si => si != null && pe.IsTrue(si.Subscription.FilterQuery) && si.Subscription.Enabled && si.Subscription.IsValid)); }
public void PredicationEngine_Predication() { Test(() => { ContentTypeInstaller.InstallContentType(CTD); var root = new SystemFolder(Repository.Root) { Name = "TestRoot" }; root.Save(); var content = Content.CreateNew("PredicationEngineTestNode", root, "PredicationEngineTestNode1"); content.Index = 42; content["DateTime1"] = new DateTime(1234, 5, 6); content["Currency1"] = 42.42; content.Save(); var prE = new PredicationEngine(content); // equality Assert.IsTrue(prE.IsTrue("+Name:predicationENGINEtestnode1")); Assert.IsFalse(prE.IsTrue("-Name:predicationENGINEtestnode1")); Assert.IsFalse(prE.IsTrue("+Name:anothername")); Assert.IsTrue(prE.IsTrue("+Index:42")); Assert.IsFalse(prE.IsTrue("-Index:42")); Assert.IsFalse(prE.IsTrue("+Index:41")); Assert.IsFalse(prE.IsTrue("+Index:43")); Assert.IsTrue(prE.IsTrue("-Index:43")); // different from ContentQuery Assert.IsTrue(prE.IsTrue("+DateTime1:'1234-05-06'")); Assert.IsFalse(prE.IsTrue("-DateTime1:'1234-05-06'")); Assert.IsFalse(prE.IsTrue("+DateTime1:'1234-05-05'")); Assert.IsTrue(prE.IsTrue("-DateTime1:'1234-05-05'")); // different from ContentQuery Assert.IsFalse(prE.IsTrue("+DateTime1:'1234-05-07'")); Assert.IsTrue(prE.IsTrue("+Currency1:42.42")); Assert.IsFalse(prE.IsTrue("-Currency1:42.42")); Assert.IsFalse(prE.IsTrue("+Currency1:42.41")); Assert.IsFalse(prE.IsTrue("+Currency1:42.43")); Assert.IsTrue(prE.IsTrue("+IsSystemContent:yes")); Assert.IsFalse(prE.IsTrue("+IsSystemContent:no")); // wildcard Assert.IsTrue(prE.IsTrue("+Name:*engine*")); Assert.IsFalse(prE.IsTrue("+Name:*Molokai*")); Assert.IsTrue(prE.IsTrue("+Name:*testnode1")); Assert.IsFalse(prE.IsTrue("+Name:*Oahu")); Assert.IsTrue(prE.IsTrue("+Name:predication*")); Assert.IsFalse(prE.IsTrue("+Name:Kauai*")); Assert.IsTrue(prE.IsTrue("+Name:predication*testnode1")); Assert.IsFalse(prE.IsTrue("+Name:Maui*Lanai")); // basic range Assert.IsTrue(prE.IsTrue("+Index:>41")); Assert.IsFalse(prE.IsTrue("+Index:>42")); Assert.IsFalse(prE.IsTrue("+Index:<42")); Assert.IsTrue(prE.IsTrue("+Index:<43")); Assert.IsTrue(prE.IsTrue("+Index:>=41")); Assert.IsTrue(prE.IsTrue("+Index:>=42")); Assert.IsTrue(prE.IsTrue("+Index:<=42")); Assert.IsTrue(prE.IsTrue("+Index:<=43")); Assert.IsTrue(prE.IsTrue("+DateTime1:>'1234-05-05'")); Assert.IsTrue(prE.IsTrue("+DateTime1:<'1234-05-07'")); Assert.IsTrue(prE.IsTrue("+DateTime1:>'999-05-07'")); Assert.IsTrue(prE.IsTrue("+Currency1:>42.41")); Assert.IsTrue(prE.IsTrue("+Currency1:<42.43")); Assert.IsTrue(prE.IsTrue("+Currency1:>9")); // extended range Assert.IsTrue(prE.IsTrue("+Index:[40 TO 44]")); Assert.IsTrue(prE.IsTrue("+Index:[40 TO 44}")); Assert.IsTrue(prE.IsTrue("+Index:{40 TO 44]")); Assert.IsTrue(prE.IsTrue("+Index:{40 TO 44}")); Assert.IsTrue(prE.IsTrue("+Index:[40 TO 42]")); Assert.IsFalse(prE.IsTrue("+Index:[40 TO 42}")); Assert.IsTrue(prE.IsTrue("+Index:{40 TO 42]")); Assert.IsFalse(prE.IsTrue("+Index:{40 TO 42}")); Assert.IsTrue(prE.IsTrue("+Index:[42 TO 44]")); Assert.IsTrue(prE.IsTrue("+Index:[42 TO 44}")); Assert.IsFalse(prE.IsTrue("+Index:{42 TO 44]")); Assert.IsFalse(prE.IsTrue("+Index:{42 TO 44}")); Assert.IsFalse(prE.IsTrue("+Index:[0 TO 40]")); Assert.IsFalse(prE.IsTrue("+Index:[0 TO 40}")); Assert.IsFalse(prE.IsTrue("+Index:{0 TO 40]")); Assert.IsFalse(prE.IsTrue("+Index:{0 TO 40}")); Assert.IsFalse(prE.IsTrue("+Index:[44 TO 50]")); Assert.IsFalse(prE.IsTrue("+Index:[44 TO 50}")); Assert.IsFalse(prE.IsTrue("+Index:{44 TO 50]")); Assert.IsFalse(prE.IsTrue("+Index:{44 TO 50}")); // complex (logical) predicates Assert.IsTrue(prE.IsTrue("-Index:41 -Index:43")); Assert.IsTrue(prE.IsTrue("-Index:41 +Index:42 -Index:43")); Assert.IsTrue(prE.IsTrue("Index:41 Index:42 Index:43")); Assert.IsFalse(prE.IsTrue("-(Index:41 Index:42 Index:43)")); // different from ContentQuery Assert.IsTrue(prE.IsTrue("-(+Index:41 +Index:42 +Index:43)")); Assert.IsTrue(prE.IsTrue("Index:(41 42 43)")); Assert.IsFalse(prE.IsTrue("-Index:(41 42 43)")); // different from ContentQuery Assert.IsTrue(prE.IsTrue("+DateTime1:'1234-05-06' +(Index:41 Index:42)")); Assert.IsFalse(prE.IsTrue("+DateTime1:'999-05-06' +(Index:41 Index:43)")); Assert.IsTrue(prE.IsTrue("DateTime1:'1234-05-06' AND (Index:41 OR Index:42)")); Assert.IsTrue(prE.IsTrue("Index:41 OR Index:42 OR Index:43")); Assert.IsTrue(prE.IsTrue("NOT Index:43")); // different from ContentQuery Assert.IsFalse(prE.IsTrue("NOT Index:42")); Assert.IsFalse(prE.IsTrue("(Index:41 AND Index:42 AND Index:43)")); Assert.IsTrue(prE.IsTrue("NOT (Index:41 AND Index:42 AND Index:43)")); // different from ContentQuery }); }