/// <summary> /// Builds a strongly typed Entity Model based on a given DXA R2 Data Model. /// </summary> /// <param name="entityModel">The strongly typed Entity Model to build. Is <c>null</c> for the first Entity Model Builder in the pipeline.</param> /// <param name="entityModelData">The DXA R2 Data Model.</param> /// <param name="baseModelType">The base type for the Entity Model to build.</param> /// <param name="localization">The context <see cref="ILocalization"/>.</param> public void BuildEntityModel(ref EntityModel entityModel, EntityModelData entityModelData, Type baseModelType, Localization localization) { using (new Tracer(entityModel, entityModelData, baseModelType, localization)) { if (entityModel == null) { throw new DxaException($"The {GetType().Name} must be configured after the DefaultModelBuilder."); } GenericTopic genericTopic = entityModel as GenericTopic; if (genericTopic != null) { Log.Debug("Generic Topic encountered..."); EntityModel stronglyTypedTopic = TryConvertToStronglyTypedTopic(genericTopic); if (stronglyTypedTopic != null) { Log.Debug($"Converted {genericTopic} to {stronglyTypedTopic}"); entityModel = stronglyTypedTopic; } else { Log.Debug($"Unable to convert {genericTopic} to Strongly Typed Topic."); } } } }
public void BuildEntityModel_TitleBodySections_Success() { string testTitle = "DITA title"; string testBody = "<div class=\"section \">First section</div><div class=\"section \">Second section</div>"; GenericTopic genericTopic = new GenericTopic { TopicTitle = "<Test topic title>", TopicBody = $"<h1 class=\"title \">{testTitle}</h1><div class=\"body \">{testBody}</div>" }; EntityModel testEntityModel = genericTopic; _testModelBuilder.BuildEntityModel(ref testEntityModel, null, null, TestFixture.ParentLocalization); OutputJson(testEntityModel); TestStronglyTypedTopic result = testEntityModel as TestStronglyTypedTopic; Assert.IsNotNull(result, "result"); Assert.AreEqual(genericTopic.TopicTitle, result.TopicTitle, "result.TopicTitle"); Assert.AreEqual(testTitle, result.Title, "result.Title"); Assert.AreEqual("First sectionSecond section", result.Body, "result.Body"); // HTML tags should get stripped ("InnerText") Assert.IsNotNull(result.BodyRichText, "result.BodyRichText"); Assert.AreEqual(testBody, result.BodyRichText.ToString(), "result.BodyRichText.ToString()"); Assert.AreEqual("First section", result.FirstSection, "result.FirstSection"); Assert.IsNotNull(result.Sections, "result.Sections"); Assert.AreEqual(2, result.Sections.Count, "result.Sections.Count"); Assert.AreEqual(result.FirstSection, result.Sections[0], "result.Sections[0]"); Assert.IsNull(result.Links, "result.Links"); Assert.IsNull(result.FirstChildLink, "result.FirstChildLink"); Assert.IsNull(result.ChildLinks, "result.ChildLinks"); Assert.IsNotNull(result.MvcData, "result.MvcData"); Assert.AreEqual(result.GetDefaultView(null), result.MvcData, "result.MvcData"); }
public void TryConvertToStronglyTypedTopic_Links_Success() { GenericTopic genericTopic = new GenericTopic { Id = "16121970", TopicBody = "<div class=\"body \" /><div class=\"related-links \">" + "<div class=\"childlink \"><strong><a class=\"link \" href=\"/firstlink.html\">First link text</a></strong></div>" + "<div class=\"childlink \"><strong><a class=\"link \" href=\"/secondlink.html\">Second link text</a></strong></div>" + "<div class=\"parentlink \"><strong><a class=\"link \" href=\"/thirdlink.html\">Third link text</a></strong></div>" + "</div>" }; TestStronglyTypedTopic result = _testModelBuilder.TryConvertToStronglyTypedTopic <TestStronglyTypedTopic>(genericTopic); Assert.IsNotNull(result, "result"); OutputJson(result); Assert.AreEqual(genericTopic.Id, result.Id, "result.Id"); Assert.IsNull(result.Title, "result.Title"); Assert.AreEqual(string.Empty, result.Body, "result.Body"); Assert.IsNotNull(result.Links, "result.Links"); Assert.AreEqual(3, result.Links.Count, "result.Links.Count"); Assert.IsNotNull(result.FirstChildLink, "result.FirstChildLink"); Assert.AreEqual("/firstlink.html", result.FirstChildLink.Url, "result.FirstChildLink.Url"); Assert.AreEqual("First link text", result.FirstChildLink.LinkText, "result.FirstChildLink.LinkText"); Assert.IsNull(result.FirstChildLink.AlternateText, "result.FirstChildLink.AlternateText"); Assert.IsNotNull(result.ChildLinks, "result.ChildLinks"); Assert.AreEqual(2, result.ChildLinks.Count, "result.ChildLinks.Count"); }
public void BuildEntityModel_TopicBodyIllFormedXml_Success() { GenericTopic genericTopic = new GenericTopic { TopicBody = "<IllFormedXML>" }; EntityModel testEntityModel = genericTopic; _testModelBuilder.BuildEntityModel(ref testEntityModel, null, null, TestFixture.ParentLocalization); Assert.AreSame(genericTopic, testEntityModel, "testEntityModel"); }
public void BuildEntityModel_NoMatchingStronglyTypedTopic_Success() { GenericTopic genericTopic = new GenericTopic { TopicBody = null }; EntityModel testEntityModel = genericTopic; _testModelBuilder.BuildEntityModel(ref testEntityModel, null, null, TestFixture.ParentLocalization); Assert.AreSame(genericTopic, testEntityModel, "testEntityModel"); }
protected void Application_Start() { InitializeDependencyInjection(); SiteConfiguration.InitializeProviders(DependencyResolver.Current.GetService); DataFormatters.Formatters.Add("json", new JsonFormatter()); DataFormatters.Formatters.Add("rss", new RssFormatter()); DataFormatters.Formatters.Add("atom", new AtomFormatter()); RegisterRoutes(RouteTable.Routes); AreaRegistration.RegisterAllAreas(); GenericTopic.Register(); // Register generic Topic View Model so that Tridion Docs content can be handled. RegisterDisplayModes(); _initialized = true; }
/// <summary> /// Tries to convert a given generic Topic to a Strongly Typed Topic Model. /// </summary> /// <param name="genericTopic">The generic Topic to convert.</param> /// <param name="ofType">The type of the Strongly Typed Topic Model to convert to. If not specified (or <c>null</c>), the type will be determined from the XHTML.</param> /// <returns>The Strongly Typed Topic Model or <c>null</c> if the generic Topic cannot be converted.</returns> public EntityModel TryConvertToStronglyTypedTopic(GenericTopic genericTopic, Type ofType = null) { using (new Tracer(genericTopic, ofType)) { Log.Debug($"Trying to convert {genericTopic} to Strongly Typed Topic Model..."); IEnumerable <Tuple <string, Type> > registeredTopicTypes = ModelTypeRegistry.GetModelTypesForVocabulary(ViewModel.DitaVocabulary); if (registeredTopicTypes == null) { Log.Debug("No Strongly Typed Topic Models registered."); return(null); } XmlElement rootElement = null; try { rootElement = ParseXhtml(genericTopic); } catch (Exception ex) { Log.Error("Unable to parse generic Topic XHTML."); Log.Debug(genericTopic.TopicBody); Log.Error(ex); return(null); } Type topicType = ofType; if (ofType == null) { topicType = DetermineTopicType(rootElement, registeredTopicTypes); if (topicType == null) { Log.Debug("No matching Strongly Typed Topic Model found."); return(null); } } EntityModel stronglyTypedTopic = BuildStronglyTypedTopic(topicType, rootElement); if (stronglyTypedTopic.Id == null) { stronglyTypedTopic.Id = genericTopic.Id; } return(stronglyTypedTopic); } }
public void TryConvertToStronglyTypedTopic_SpecializedTopic_Success() { string testTitle = "DITA title"; string testBody = "<div class=\"section lcIntro \" id=\"s1\">Intro section</div><div class=\"section lcObjectives \" id=\"s2\">Objectives section</div>"; GenericTopic genericTopic = new GenericTopic { TopicTitle = "Specialized topic title", TopicBody = $"<h1 class=\"title \">{testTitle}</h1><div class=\"body lcBaseBody lcOverviewBody \" id=\"b1\">{testBody}</div>" }; TestSpecializedTopic result = _testModelBuilder.TryConvertToStronglyTypedTopic(genericTopic) as TestSpecializedTopic; Assert.IsNotNull(result, "result"); OutputJson(result); Assert.IsNotNull(result.Intro, "result.Intro"); Assert.IsNotNull(result.Objectives, "result.Objectives"); Assert.IsNotNull(result.Body, "result.Body"); Assert.IsNotNull(result.Body.Intro, "result.Body.Intro"); Assert.IsNotNull(result.Body.Objectives, "result.Body.Objectives"); Assert.IsNotNull(result.Body.Objectives.Content, "result.Body.Objectives.Content"); Assert.IsNotNull(result.Body.Sections, "result.Body.Sections"); Assert.AreEqual("Intro section", result.Intro.ToString(), "result.Intro.ToString()"); Assert.AreEqual("Objectives section", result.Objectives.ToString(), "result.Objectives.ToString()"); Assert.AreEqual("b1", result.Body.Id, "result.Body.Id"); Assert.AreEqual("body lcBaseBody lcOverviewBody ", result.Body.HtmlClasses, "body lcBaseBody lcOverviewBody "); Assert.AreEqual("Intro section", result.Body.Intro.ToString(), "result.Body.Intro.ToString()"); Assert.AreEqual("s2", result.Body.Objectives.Id, "result.Body.Objectives.Id"); Assert.AreEqual("section lcObjectives ", result.Body.Objectives.HtmlClasses, "result.Body.Objectives.HtmlClasses"); Assert.AreEqual("Objectives section", result.Body.Objectives.Content.ToString(), "result.Body.Objectives.Content.ToString()"); Assert.AreEqual(2, result.Body.Sections.Count, "result.Body.Sections.Count"); Assert.AreEqual("s1", result.Body.Sections[0].Id, "result.Body.Sections[0].Id"); Assert.AreEqual("s2", result.Body.Sections[1].Id, "result.Body.Sections[1].Id"); Assert.AreEqual("section lcIntro ", result.Body.Sections[0].HtmlClasses, "result.Body.Sections[0].HtmlClasses"); Assert.AreEqual("section lcObjectives ", result.Body.Sections[1].HtmlClasses, "result.Body.Sections[1].HtmlClasses"); Assert.IsNotNull(result.MvcData, "result.MvcData"); Assert.AreEqual(result.GetDefaultView(null), result.MvcData, "result.MvcData"); Assert.IsNotNull(result.Body.MvcData, "result.Body.MvcData"); Assert.AreEqual(result.Body.GetDefaultView(null), result.Body.MvcData, "result.Body.MvcData"); }
protected virtual XmlElement ParseXhtml(GenericTopic genericTopic) { using (new Tracer(genericTopic)) { XmlDocument topicXmlDoc = new XmlDocument(); topicXmlDoc.LoadXml($"<topic>{genericTopic.TopicBody}</topic>"); XmlElement topicElement = topicXmlDoc.DocumentElement; // Inject GenericTopic's TopicTitle as additional HTML element XmlElement topicTitleElement = topicXmlDoc.CreateElement("h1"); topicTitleElement.SetAttribute("class", "_topicTitle"); topicTitleElement.InnerText = genericTopic.TopicTitle; topicElement.AppendChild(topicTitleElement); return(topicElement); } }
public void BuildEntityModel_ThroughModelBuilderPipeline_Success() { Localization testLocalization = new DocsLocalization(); testLocalization.EnsureInitialized(); string testTopicId = "1612-1970"; string testTitle = "DITA title"; string testBody = "<div class=\"section \">First section</div><div class=\"section \">Second section</div>"; GenericTopic genericTopic = new GenericTopic { TopicTitle = "<Test topic title>", TopicBody = $"<h1 class=\"title \">{testTitle}</h1><div class=\"body \">{testBody}</div>" }; PageModelData testPageModelData = new PageModelData { Id = "666", Regions = new List <RegionModelData> { new RegionModelData { Name = "Main", Entities = new List <EntityModelData> { new EntityModelData { Id = testTopicId, SchemaId = "1", // Tridion Docs uses a hard-coded/fake Schema ID. Content = new ContentModelData { { "topicTitle", genericTopic.TopicTitle }, { "topicBody", genericTopic.TopicBody } }, MvcData = new DataModel.MvcData { AreaName = "Ish", ViewName = "Topic" } } }, MvcData = new DataModel.MvcData { AreaName = "Core", // TODO: test with ISH data ViewName = "Main" } } }, MvcData = new DataModel.MvcData { AreaName = "Test", ViewName = "SimpleTestPage" } }; PageModel pageModel = ModelBuilderPipeline.CreatePageModel(testPageModelData, false, testLocalization); Assert.IsNotNull(pageModel, "pageModel"); OutputJson(pageModel); TestStronglyTypedTopic result = pageModel.Regions["Main"].Entities[0] as TestStronglyTypedTopic; Assert.IsNotNull(result); Assert.AreEqual(testTopicId, result.Id, "result.Id"); Assert.AreEqual(genericTopic.TopicTitle, result.TopicTitle, "result.TopicTitle"); Assert.AreEqual(testTitle, result.Title, "result.Title"); Assert.AreEqual(testBody, result.BodyRichText.ToString(), "result.BodyRichText.ToString()"); Assert.AreEqual("First section", result.FirstSection, "result.FirstSection"); Assert.AreEqual(result.GetDefaultView(null), result.MvcData, "result.MvcData"); }
/// <summary> /// Tries to convert a given generic Topic to a Strongly Typed Topic Model. /// </summary> /// <param name="genericTopic">The generic Topic to convert.</param> /// <typeparam name="T">The type of the Strongly Typed Topic Model to convert to.</typeparam> /// <returns>The Strongly Typed Topic Model or <c>null</c> if the generic Topic cannot be converted to the given type.</returns> public T TryConvertToStronglyTypedTopic <T>(GenericTopic genericTopic) where T : EntityModel => (T)TryConvertToStronglyTypedTopic(genericTopic, typeof(T));
internal static void RegisterViewModels() { // Entity Views RegisterViewModel("Article", typeof(Article)); RegisterViewModel("Image", typeof(Image)); RegisterViewModel("Download", typeof(Download)); RegisterViewModel("TestEntity", typeof(TestEntity)); RegisterViewModel("LanguageSelector", typeof(Common.Models.Configuration)); RegisterViewModel("Breadcrumb", typeof(NavigationLinks), "Navigation"); RegisterViewModel("LeftNavigation", typeof(NavigationLinks), "Navigation"); RegisterViewModel("SiteMap", typeof(SitemapItem), "Navigation"); RegisterViewModel("SiteMapXml", typeof(SitemapItem), "Navigation"); RegisterViewModel("TopNavigation", typeof(NavigationLinks), "Navigation"); RegisterViewModel("PagedList", typeof(ContentList <Teaser>), "List"); RegisterViewModel("Test:TSI1758Test", typeof(Tsi1758TestEntity)); RegisterViewModel("Test:TSI1946Test", typeof(Tsi1946TestEntity)); RegisterViewModel("Test:TSI811Test", typeof(Tsi811TestEntity)); RegisterViewModel("MediaManager:imagedist", typeof(MediaManagerDistribution)); RegisterViewModel("Test:TSI1757Test1", typeof(Tsi1757TestEntity1)); RegisterViewModel("Test:TSI1757Test2", typeof(Tsi1757TestEntity2)); RegisterViewModel("Test:TSI1757Test3", typeof(Tsi1757TestEntity3)); RegisterViewModel("Test:CompLinkTest", typeof(CompLinkTest)); RegisterViewModel("Test:TSI2316Test", typeof(Tsi2316TestEntity)); RegisterViewModel("Test:TSI2844Test", typeof(Tsi2844TestEntity)); RegisterViewModel("Test:TSI3010Test", typeof(Tsi3010TestEntity)); GenericTopic.Register(); // Generic Topic Model // Strongly Typed Topic Models RegisterViewModel(typeof(TestStronglyTypedTopic)); RegisterViewModel(typeof(TestSpecializedTopic)); // Page Views RegisterViewModel("GeneralPage", typeof(PageModel)); RegisterViewModel("IncludePage", typeof(PageModel)); RegisterViewModel("RedirectPage", typeof(PageModel)); RegisterViewModel("Test:SimpleTestPage", typeof(PageModel)); RegisterViewModel("Test:TSI811TestPage", typeof(Tsi811PageModel)); RegisterViewModel("Test:TSI2285TestPage", typeof(Tsi2285PageModel)); // Region Views RegisterViewModel("2-Column", typeof(RegionModel)); RegisterViewModel("3-Column", typeof(RegionModel)); RegisterViewModel("4-Column", typeof(RegionModel)); RegisterViewModel("Hero", typeof(RegionModel)); RegisterViewModel("Info", typeof(RegionModel)); RegisterViewModel("Left", typeof(RegionModel)); RegisterViewModel("Links", typeof(RegionModel)); RegisterViewModel("Logo", typeof(RegionModel)); RegisterViewModel("Main", typeof(RegionModel)); RegisterViewModel("Nav", typeof(RegionModel)); RegisterViewModel("Tools", typeof(RegionModel)); RegisterViewModel("SmartTarget:SmartTargetRegion", typeof(SmartTargetRegion)); RegisterViewModel("SmartTarget:2-Column", typeof(SmartTargetRegion)); // Region Views for Include Pages RegisterViewModel("Header", typeof(RegionModel)); RegisterViewModel("Footer", typeof(RegionModel)); RegisterViewModel("Left Navigation", typeof(RegionModel)); RegisterViewModel("Content Tools", typeof(RegionModel)); }