public void CreateContextFromMultiBranchDictionarySearchTest() { ContextValueDictionary cvd = new ContextValueDictionary(); var context = new EmployeeContext(); var parser = new Parser(); parser.Parse(context); cvd.CreateValue <EmployeeContext, EmployeeId>(parser, "0001"); cvd.CreateValue <EmployeeContext, PersonContext, PersonNameContext, FirstName>(parser, "Marc"); cvd.CreateValue <EmployeeContext, PersonContext, PersonNameContext, LastName>(parser, "Clifton"); var search = new PersonNameContext(); var searchParser = new Parser(); searchParser.Parse(search); var cvFirstName = searchParser.CreateValue <PersonNameContext, FirstName>("Marc"); List <ContextNode> matches = cvd.Search(cvFirstName); Assert.IsTrue(matches.Count == 1); // TODO: We should be asserting the values from the match record! /* * var (newParser, newContext) = cvd.CreateContext(matches[0]); * Assert.IsTrue(newParser.FieldContextPaths[0].Field.ContextValue.Value == "0001"); * Assert.IsTrue(newParser.FieldContextPaths[1].Field.ContextValue.Value == "Marc"); * Assert.IsTrue(newParser.FieldContextPaths[2].Field.ContextValue.Value == "Clifton"); */ }
/// <summary> /// Returns HTML rendering the current state of the dictionary tree. /// </summary> public void Process(ISemanticProcessor proc, IMembrane membrane, GetDictionaryTreeHtml msg) { ContextValueDictionary cvd = CreateOrGetContextValueDictionary(proc, msg.Context); StringBuilder sb = new StringBuilder(); List <Guid> path = new List <Guid>(); NavigateChildren(sb, cvd.Root.Children, 0, path, msg.ShowInstanceIDs); JsonResponse(proc, msg, new { Status = "OK", html = sb.ToBase64String() }); }
public void CreatingDuplicateContextValuePathShouldAssertTest() { ContextValueDictionary cvd = new ContextValueDictionary(); var context = new ParentContext(); var parser = new Parser(); parser.Parse(context); cvd.CreateValue <ParentContext, PersonContext, PersonNameContext, FirstName>(parser, "John"); cvd.CreateValue <ParentContext, PersonContext, PersonNameContext, FirstName>(parser, "Jane"); }
public void Process(ISemanticProcessor proc, IMembrane membrane, UpdateField msg) { ContextValueDictionary cvd = CreateOrGetContextValueDictionary(proc, msg.Context); var instancePath = msg.ID.Split(".").Select(Guid.Parse).ToList(); var typePath = msg.TypePath.Split("|").ToList(); var cv = new ContextValue(msg.Value, instancePath, typePath.Select(t => Type.GetType(t)).ToList(), msg.RecordNumber); cvd.AddOrUpdate(cv); JsonResponse(proc, msg, new OKResponse()); }
protected ContextValueDictionary CreateOrGetContextValueDictionary(ISemanticProcessor proc, Clifton.WebInterfaces.IContext context) { ContextValueDictionary cvd; IWebSessionService session = proc.ServiceManager.Get <IWebSessionService>(); if (!session.TryGetSessionObject(context, "CVD", out cvd)) { cvd = new ContextValueDictionary(); session.SetSessionObject(context, "CVD", cvd); } return(cvd); }
// Ex: http://localhost/renderContext?ContextName=MeaningExplorer.PersonContext // Ex: http://localhost/renderContext?ContextName=MeaningExplorer.PersonContext&isSearch=true public void Process(ISemanticProcessor proc, IMembrane membrane, RenderContext msg) { try { Type t = Type.GetType(msg.ContextName); Clifton.Meaning.IContext context = (Clifton.Meaning.IContext)Activator.CreateInstance(t); string html; try { Parser parser = new Parser(); parser.Log = logMsg => Console.WriteLine(logMsg); parser.Parse(context); if (parser.AreDeclarationsValid) { ShowGroups(parser.Groups); // The CVD is needed for rendering lookup values. ContextValueDictionary cvd = CreateOrGetContextValueDictionary(proc, msg.Context); html = Renderer.CreatePage(parser, msg.IsSearch ? Renderer.Mode.Search : Renderer.Mode.NewRecord, cvd); } else { html = "<p>Context declarations are not valid. Missing entities:</p>" + String.Join("<br>", parser.MissingDeclarations.Select(pt => pt.Name)); } } catch (Exception ex) { html = "<p>Context declarations are not valid.</p><p>" + ex.Message + "</p>"; html = html + "<p>" + ex.StackTrace.Replace("\r\n", "<br>"); } proc.ProcessInstance <WebServerMembrane, HtmlResponse>(r => { r.Context = msg.Context; r.Html = html; }); } catch (Exception ex) { proc.ProcessInstance <WebServerMembrane, HtmlResponse>(r => { r.Context = msg.Context; r.Html = ex.Message + "<br>" + ex.StackTrace.Replace("\r\n", "<br>"); }); } }
public void CreateContextFromDictionarySearchTest() { ContextValueDictionary cvd = new ContextValueDictionary(); // An example of two different contexts having a PersonNameContext. var context1 = new EmployeeName(); var parser1 = new Parser(); parser1.Parse(context1); // Set the same values in the firstname/lastname fields of the two different contexts. var cv0fn = cvd.CreateValue <EmployeeName, PersonNameContext, FirstName>(parser1, "Marc"); var cv0ln = cvd.CreateValue <EmployeeName, PersonNameContext, LastName>(parser1, "Clifton"); var search = new PersonNameContext(); var searchParser = new Parser(); searchParser.Parse(search); var cvFirstName = searchParser.CreateValue <PersonNameContext, FirstName>("Marc"); var cvLastName = searchParser.CreateValue <PersonNameContext, LastName>("Clifton"); List <ContextNode> matches = cvd.Search(cvFirstName, cvLastName); Assert.IsTrue(matches.Count == 1); Assert.IsTrue(parser1.FieldContextPaths[0].Path.Count == 3); Assert.IsTrue(parser1.FieldContextPaths[1].Path.Count == 3); // TODO: We should be asserting the values from the match record! /* * var (newParser, newContext) = cvd.CreateContext(matches[0]); * * // Verify that the parser's field context path ID's match the dictionary ID's and * // the actual ContextValue matches the * * //Assert.IsTrue(cv0fn.InstancePath[0] == newParser.FieldContextPaths[0].Path[0].InstanceId); * //Assert.IsTrue(cv0fn.InstancePath[1] == newParser.FieldContextPaths[0].Path[1].InstanceId); * //Assert.IsTrue(cv0fn.InstancePath[2] == newParser.FieldContextPaths[0].Path[2].InstanceId); * * //Assert.IsTrue(cv0ln.InstancePath[0] == newParser.FieldContextPaths[1].Path[0].InstanceId); * //Assert.IsTrue(cv0ln.InstancePath[1] == newParser.FieldContextPaths[1].Path[1].InstanceId); * //Assert.IsTrue(cv0ln.InstancePath[2] == newParser.FieldContextPaths[1].Path[2].InstanceId); * * Assert.IsTrue(newParser.FieldContextPaths[0].Field.ContextValue.Value == "Marc"); * Assert.IsTrue(newParser.FieldContextPaths[1].Field.ContextValue.Value == "Clifton"); */ }
public void Process(ISemanticProcessor proc, IMembrane membrane, ViewContext msg) { var instancePath = msg.InstancePath.Split(".").Select(s => Guid.Parse(s)).ToList(); ContextValueDictionary cvd = CreateOrGetContextValueDictionary(proc, msg.Context); // var (parser, context) = cvd.CreateContext(instancePath); // TODO: WHY ARE WE EVEN DOING THIS? IT SEEMS ALL WE NEED TO DO IS CREATE THE PARSER! // var (parser, fullInstancePath) = cvd.CreateContext(instancePath.First()); Guid rootId = instancePath.First(); Type rootType = cvd.GetRootType(rootId); Parser parser = new Parser(); var context = (Context)Activator.CreateInstance(rootType); parser.Parse(context); string html = Renderer.CreatePage(parser, Renderer.Mode.View, cvd, rootId); JsonResponse(proc, msg, new { Status = "OK", html = html.ToString().ToBase64String() }); }
/// <summary> /// Returns HTML rendering the current state of the dictionary nodes. /// </summary> public void Process(ISemanticProcessor proc, IMembrane membrane, GetDictionaryNodesHtml msg) { ContextValueDictionary cvd = CreateOrGetContextValueDictionary(proc, msg.Context); StringBuilder sb = new StringBuilder(); foreach (var kvp in cvd.FlatView) { sb.Append(kvp.Key.Name + " : <br>"); foreach (var node in kvp.Value) { if (node.ContextValue != null) { sb.Append("  "); sb.Append(" = " + node.ContextValue.Value); sb.Append("<br>"); } } } JsonResponse(proc, msg, new { Status = "OK", html = sb.ToBase64String() }); }
public void Process(ISemanticProcessor proc, IMembrane membrane, SearchContext msg) { List <ContextValue> cvSearch = new List <ContextValue>(); foreach (var search in msg.SearchFields) { var instancePath = search.ID.Split(".").Select(Guid.Parse).ToList(); var typePath = search.TypePath.Split("|").ToList(); var cv = new ContextValue(search.Value, instancePath, typePath.Select(t => Type.GetType(t)).ToList()); cvSearch.Add(cv); } ContextValueDictionary cvd = CreateOrGetContextValueDictionary(proc, msg.Context); // We want unique context instances, as the search will return all context paths based on the search context values. List <ContextNode> matches = cvd.Search(cvSearch).DistinctBy(cn => cn.InstanceId).ToList(); var results = matches.Select(m => cvd.GetPath(m)); var html = Render(results); JsonResponse(proc, msg, new { Status = "OK", html = html.ToString().ToBase64String() }); }
public void MultiRowSearchTest() { ContextValueDictionary cvd = new ContextValueDictionary(); var context = new ParentContext(); var parser = new Parser(); parser.Parse(context); cvd.CreateValue <ParentContext, PersonContext, PersonNameContext, FirstName>(parser, "John"); cvd.CreateValue <ParentContext, PersonContext, PersonNameContext, LastName>(parser, "Doe"); cvd.CreateValue <ParentContext, ChildContext, PersonContext, PersonNameContext, FirstName>(parser, "Jane", 0); cvd.CreateValue <ParentContext, ChildContext, PersonContext, PersonNameContext, LastName>(parser, "Doe", 0); cvd.CreateValue <ParentContext, ChildContext, PersonContext, PersonNameContext, FirstName>(parser, "Joey", 1); cvd.CreateValue <ParentContext, ChildContext, PersonContext, PersonNameContext, LastName>(parser, "Doe", 1); var search = new PersonNameContext(); var searchParser = new Parser(); searchParser.Parse(search); var cvFirstName = searchParser.CreateValue <PersonNameContext, LastName>("Doe"); List <ContextNode> matches = cvd.Search(cvFirstName); }
public static string CreatePage(Parser parser, Mode mode = Mode.NewRecord, ContextValueDictionary cvd = null, Guid rootId = default(Guid)) { StringBuilder sb = new StringBuilder(); List <LookupItem> lookupDictionary = new List <LookupItem>(); sb.StartHtml(); sb.StartHead(). Script("/js/wireUpValueChangeNotifier.js"). Stylesheet("/css/styles.css"). EndHead(); sb.StartBody(); foreach (var group in parser.Groups) { // Bizarre alternatives: //(group.ContextPath.Count() == 0 ? new Action(()=>sb.StartDiv()) : new Action(()=>sb.StartInlineDiv()))(); //var throwAway = group.ContextPath.Count() == 0 ? sb.StartDiv() : sb.StartInlineDiv(); if (group.ContextPath.Count() == 0) { // sb.StartDiv(); sb.StartInlineDiv(); } else { sb.StartInlineDiv(); // sb.StartDiv(); } // if (group.Relationship.GetType() != typeof(NullRelationship)) if (group.Relationship.RelationshipType != typeof(NullRelationship)) { // TODO: If the mode is search, then we only want to display one instance, and not as a grid. if (group.Relationship.Maximum < 6 && !group.Relationship.RenderAsGrid) { for (int recNum = 0; recNum < group.Relationship.Maximum; recNum++) { // multiple instances are stacked vertically. sb.StartDiv(); // Horizontal stacking: // sb.StartInlineDiv(); CreateFieldset(parser, sb, lookupDictionary, group, mode, cvd, rootId, recNum, group.Relationship.Minimum); sb.EndDiv(); } } else { // TODO: Some arbitrary cutoff would change the fieldset to use a grid instead of discrete text input's. CreateGrid(parser, sb, group, mode, cvd, rootId, group.Relationship.Minimum, group.Relationship.Maximum); // CreateFieldset(parser, sb, group, mode, cvd, rootId); } } else { CreateFieldset(parser, sb, lookupDictionary, group, mode, cvd, rootId); } sb.EndDiv(); // if there's no path, the next group does on the next line, otherwise the groups start stacking horizontally. if (group.ContextPath.Count() == 0) { // https://css-tricks.com/the-how-and-why-of-clearing-floats/ sb.StartDiv().CustomStyle("clear", "both").EndDiv(); } sb.Append("\r\n"); } // https://css-tricks.com/the-how-and-why-of-clearing-floats/ sb.StartDiv().CustomStyle("clear", "both").EndDiv(); sb.StartDiv(); switch (mode) { case Mode.Search: sb.StartButton().ID("searchContext").Class("margintop10").Append("Search Context").EndButton(); sb.StartParagraph().Append("<b>Search Results:</b>").EndParagraph(); sb.StartParagraph().StartDiv().ID("searchResults").EndDiv().EndParagraph(); sb.StartParagraph().StartDiv().ID("viewSelectedItem").EndDiv().EndParagraph(); break; case Mode.NewRecord: sb.StartButton().ID("newContext").Class("margintop10").Append("New Context").EndButton(); sb.StartParagraph().Append("<b>Dictionary:</b>").EndParagraph(); sb.StartParagraph().StartDiv().ID("dictionary").EndDiv().EndParagraph(); sb.StartParagraph().Append("<b>Type Nodes:</b>").EndParagraph(); sb.StartParagraph().StartDiv().ID("nodes").EndDiv().EndParagraph(); break; } sb.EndDiv(); string jsonLookupDict = JsonConvert.SerializeObject(lookupDictionary, Formatting.Indented); sb.Append(CRLF); sb.StartScript().Append(CRLF). Javascript("(function() {wireUpValueChangeNotifier(); wireUpEvents();})();"). Append(CRLF). Javascript("lookupDictionary = " + jsonLookupDict + ";"). Append(CRLF). EndScript(). Append(CRLF); sb.EndBody().EndHtml(); return(sb.ToString()); }
private static void CreateGrid(Parser parser, StringBuilder sb, Group group, Mode mode, ContextValueDictionary cvd, Guid rootId, int min, int max) { sb.StartFieldSet().Legend(group.Name); sb.StartTable(); // Create headers sb.StartRow(); foreach (var field in group.Fields) { sb.StartHeader().Append(field.Label).EndHeader(); } sb.EndRow(); // int recNum = 0; // For giggles, let's create 20 rows for (int recNum = 0; recNum < 20.Min(max); recNum++) { sb.StartRow(); foreach (var field in group.Fields) { string fieldValue = field.ContextValue?.Value ?? ""; List <Guid> instanceIdList = new List <Guid>(); // If viewing an existing record, don't create a new instanceID for the field. if (mode != Mode.View) { // Here we want to bind the field's context path type list, up to the path that contains the context value, // with ID's for the path types, creating ID's if the path type doesn't exist. This ensures that all data instances // exist within a single root context. instanceIdList = parser.CreateInstancePath(field.ContextPath.Select(cp => cp.Type)); } else { Assert.That(cvd != null, "ContextValueDictionary must be provided when viewing existing context data."); Assert.That(rootId != Guid.Empty, "A non-empty root ID is required when viewing existing context data."); // In view mode, the context path to the field [context path - 1] should match a dictionary entry, // then we need to acquire the instance ID for the record number and type of the actual ContextValue. // If there is no record number entry, the value is assigned to "". if (cvd.TryGetContextNode(field, rootId, recNum, out ContextNode cn, out List <Guid> instanceIdPath)) { instanceIdList = instanceIdPath; fieldValue = cn.ContextValue.Value; }
public void TwoContextsShareValuesTest() { ContextValueDictionary cvd = new ContextValueDictionary(); // An example of two different contexts having a PersonNameContext. var context1 = new EmployeeName(); var context2 = new AddressBookName(); // We add a third context that should not match the search criteria. var context3 = new EmployeeName(); var parser1 = new Parser(); var parser2 = new Parser(); var parser3 = new Parser(); parser1.Parse(context1); parser2.Parse(context2); parser3.Parse(context3); Assert.IsTrue(parser1.Groups.Count == 1); Assert.IsTrue(parser2.Groups.Count == 1); Assert.IsTrue(parser3.Groups.Count == 1); Assert.IsTrue(parser1.Groups[0].Fields.Count == 2); Assert.IsTrue(parser2.Groups[0].Fields.Count == 2); Assert.IsTrue(parser3.Groups[0].Fields.Count == 2); Assert.IsTrue(parser1.Groups[0].Fields[0].ContextPath.Count == 3); Assert.IsTrue(parser2.Groups[0].Fields[0].ContextPath.Count == 3); Assert.IsTrue(parser3.Groups[0].Fields[0].ContextPath.Count == 3); // Set the same values in the firstname/lastname fields of the two different contexts. var cv0fn = cvd.CreateValue <EmployeeName, PersonNameContext, FirstName>(parser1, "Marc"); var cv0ln = cvd.CreateValue <EmployeeName, PersonNameContext, LastName>(parser1, "Clifton"); var cv1fn = cvd.CreateValue <AddressBookName, PersonNameContext, FirstName>(parser2, "Marc"); var cv1ln = cvd.CreateValue <AddressBookName, PersonNameContext, LastName>(parser2, "Clifton"); cvd.CreateValue <EmployeeName, PersonNameContext, FirstName>(parser3, "Ian"); cvd.CreateValue <EmployeeName, PersonNameContext, LastName>(parser3, "Clifton"); // TODO: Tie in a context instance with a parser for that instance so we're working with a unified object. /* * // Alternate way of doing this directly from the parser groups. * * var c1f1 = parser1.Groups[0].Fields[0]; * var c1f2 = parser1.Groups[0].Fields[1]; * var c2f1 = parser2.Groups[0].Fields[0]; * var c2f2 = parser2.Groups[0].Fields[1]; * var c3f1 = parser3.Groups[0].Fields[0]; * var c3f2 = parser3.Groups[0].Fields[1]; * * cvd.Add(c1f1.CreateValue("Marc")); * cvd.Add(c1f2.CreateValue("Clifton")); * * cvd.Add(c2f1.CreateValue("Marc")); * cvd.Add(c2f2.CreateValue("Clifton")); * * // Create a first/last name context that should not match. * cvd.Add(c3f1.CreateValue("Ian")); * cvd.Add(c3f2.CreateValue("Clifton")); */ // When we ask what contexts these values exist, we should get back two context paths // as the search criteria (below) exists in two different context. var search = new PersonNameContext(); var searchParser = new Parser(); searchParser.Parse(search); //var searchFirstNameField = searchParser.Groups[0].Fields[0]; //var searchLastNameField = searchParser.Groups[0].Fields[1]; //var cvFirstName = searchFirstNameField.CreateValue("Marc"); //var cvLastName = searchLastNameField.CreateValue("Clifton"); // Use the parser to create the search context -- if we use the context value dictionary, the // context values get stored in the dictionary, which we don't want! var cvFirstName = searchParser.CreateValue <PersonNameContext, FirstName>("Marc"); var cvLastName = searchParser.CreateValue <PersonNameContext, LastName>("Clifton"); List <ContextNode> matches = cvd.Search(cvFirstName, cvLastName); Assert.IsTrue(matches.Count == 2); Assert.IsTrue(matches.Any(m => m.Parent.Type == typeof(EmployeeName))); Assert.IsTrue(matches.Any(m => m.Parent.Type == typeof(AddressBookName))); Assert.IsTrue(matches[0].Children[0].InstanceId == cv0fn.InstanceId); Assert.IsTrue(matches[0].Children[1].InstanceId == cv0ln.InstanceId); Assert.IsTrue(matches[1].Children[0].InstanceId == cv1fn.InstanceId); Assert.IsTrue(matches[1].Children[1].InstanceId == cv1ln.InstanceId); Assert.IsTrue(matches[0].Children.Any(c => c.ContextValue.Value == "Marc")); Assert.IsTrue(matches[0].Children.Any(c => c.ContextValue.Value == "Clifton")); Assert.IsTrue(matches[1].Children.Any(c => c.ContextValue.Value == "Marc")); Assert.IsTrue(matches[1].Children.Any(c => c.ContextValue.Value == "Clifton")); }