Showing posts with label sitecore. Show all posts
Showing posts with label sitecore. Show all posts

Sunday, January 9, 2011

UML diagramming for Sitecore templates

A while ago, the guys from Hedgehog posted a teaser showing a diagram that supposedly was generated by a coming plugin. Because I do most of my diagramming in Enterprise Architect, which supports importing XMI files, I was wondering: How hard is it to generate a minimal version of XMI, that is constructed based on the template hierarchy in a Sitecore Solution?
If I would make it work, I could generate UML Class diagrams by importing a XMI file into Enterprise Architect!
As show below, this is very easy. What I did:
  1. create a simple class diagram (containing only 2 classes, 2 properties and inheritance)
  2. Exported the class diagram to a simple XMI file
  3. Pasted This XMI into a Layout
  4. Created some logic that supplies repeaters with template information
  5. added repeaters to the aspx, that made the XMI file dynamic
  6. visit a page that 'has' the layout bound to it
  7. voila! a valid XMI file that I can import into Enterprise Architect
Check the images below on the steps I took:

step 1: create a simple class diagram


  1. <packagedElement xmi:type="uml:Class" xmi:id="EAID_B16F5263_B589_479e_8588_CD3EA2BCF8A7" name="Class1" visibility="public">
  2.     <ownedAttribute xmi:type="uml:Property" xmi:id="EAID_49CFB4AF_DF06_48b1_824C_7025907761B1" name="name1" visibility="private" isDerived="false" isOrdered="false"></ownedAttribute>
  3. </packagedElement>
  4. <packagedElement xmi:type="uml:Class" xmi:id="EAID_AD064C48_D2D0_4d00_B739_6E3E8A78005A" name="subclass2" visibility="public">
  5.     <ownedAttribute xmi:type="uml:Property" xmi:id="EAID_AF11B4D8_CD8D_45a0_BC48_9D5E53F06FFB" name="Description2" visibility="private" isDerived="false" isOrdered="false"></ownedAttribute>
  6.     <generalization xmi:type="uml:Generalization" xmi:id="EAID_A05EA125_D602_4d01_B338_31C793A08B12" general="EAID_B16F5263_B589_479e_8588_CD3EA2BCF8A7"/>
  7. </packagedElement>
Step 2: a fragment of the XMI file,it contains the 2 classes, properties and de generalization (=inheritance)




  1.         public List<TemplateItem> Templates
  2.         {
  3.             get
  4.             {
  5.                 List<TemplateItem> lTemplates = new List<TemplateItem>();
  6.                 var lSelected = (from Item lItem in Sitecore.Context.Item.GetSelectedItems("IncludedRoots") select lItem);
  7.                 foreach (Item lItem in lSelected)
  8.                 {
  9.                     if(lItem.TemplateName == "Template")
  10.                     {
  11.                         lTemplates.Add(Factory.GetDatabase("master").GetTemplate(lItem.ID));
  12.                     }
  13.                     else
  14.                     {
  15.                         lTemplates.AddRange(from lTemplateItem
  16.                                             in lItem.GetChildrenDescendantOfTemplate("Template", 10)
  17.                                             where lTemplateItem.TemplateName == "Template"
  18.                                             select Factory.GetDatabase("master").GetTemplate(lTemplateItem.ID));
  19.                     }

  20.                 }
  21.                 return lTemplates.OrderBy(a => a.Name).ToList();
  22.             }
  23.         }
step 4: a collection of templates; I used an item with a "included roots" field, it contains selected template(folders)




  1. <asp:Repeater ID="Repeater1" runat="server" DataSource="<%#Templates%>">
  2.         <ItemTemplate>
  3.             <packagedElement xmi:type="uml:Class" xmi:id="<%#((CustomItemBase)Container.DataItem).ID.ToShortID()%>" name="<%#((CustomItemBase)Container.DataItem).Name%>" visibility="public">
  4.             <asp:Repeater ID="rptSections" runat="server" DataSource='<%#GetFields(((TemplateItem)Container.DataItem))%>'>
  5.                 <ItemTemplate><asp:PlaceHolder runat="server" visible="<%#((TemplateFieldItem)Container.DataItem).Section.Template.Name==((CustomItemBase)Container.GetParentContainerDataItem().DataItem).Name%>">
  6.                 <ownedAttribute xmi:type="uml:Property" xmi:id="<%#((TemplateFieldItem)Container.DataItem).ID.ToShortID()%>" name="<%#((TemplateFieldItem)Container.DataItem).Name%>" visibility="private" isDerived="<%#((TemplateFieldItem)Container.DataItem).Section.Template.Name!=((CustomItemBase)Container.GetParentContainerDataItem().DataItem).Name%>" isOrdered="false">
  7.                 <type xmi:idref="<%#((TemplateFieldItem)Container.DataItem).Type%>"/>
  8.                 <asp:PlaceHolder runat="server" visible="<%#!string.IsNullOrEmpty(((TemplateFieldItem)Container.DataItem).GetStandardValue())%>"><defaultValue xmi:id="<%#((TemplateFieldItem)Container.DataItem).ID.ToShortID()%>" value="<%#((TemplateFieldItem)Container.DataItem).GetStandardValue()%>"/></asp:PlaceHolder>
  9.                 </ownedAttribute>
  10.                 </asp:PlaceHolder></ItemTemplate>
  11.             </asp:Repeater>    
  12.             <asp:Repeater ID="rptBaseTemplates" runat="server" DataSource="<%#((TemplateItem)Container.DataItem).BaseTemplates%>">
  13.                 <ItemTemplate><!-- <%#((CustomItemBase)Container.DataItem).Name%> -->
  14.                 <generalization xmi:type="uml:Generalization" xmi:id="<%=Sitecore.Data.ID.NewID.ToShortID() %>" general="<%#((CustomItemBase)Container.DataItem).ID.ToShortID()%>"/> </ItemTemplate>
  15.             </asp:Repeater>  
  16.             </packagedElement>
  17.         </ItemTemplate>
step 5: the Repeater

Final: A class diagram, created from am imported XMI file!

Really nice, don't you think?
2 things I want do do next:
  1. make the XMI generation work in the Compiled Domain Model shared source module
  2. generate the rest of the documentation, with more info per template/field
That's it, ff you would like some sources, leave a note!
All links in this article are available here.

Tuesday, December 28, 2010

Razor for MVC in Sitecore

Like Peter in his comment to Alex' blog here, I'm also not a big fan of XLST's. I've seen several discussions about (not) using XSLT's in Sitecore with good arguments and even Sitecore has arguments for both. Fact remains, not all the people involved in Sitecore projects know asp.net, could the new Razor syntax in MVC be a viable solution here?
Is the following code fragment easier than it's XSLT counterpart?
 <ul>  
@foreach (var aChild in Item.Children.Where(Child => Child["ShowInMenu"] != "0"))  
{  
<li>@aChild.Name</li>  
}  
</ul>  

That is a simple sample, but what about "Creating a tree like left menu"? In XSLT Brian Pedersen does it like this, a very good sample. What would that look like in Razor? A simple sample, without reuse/recursion:
 <ul>  
@foreach (var aChild in Item.Children.Where(Child => Child["ShowInMenu"] != "0"))  
{  
<li>@aChild.Name  
<ul>  
@foreach (var bChild in aChild.Children.Where(Child => Child["ShowInMenu"] != "0"))  
{  
<li>@bChild.Name</li>  
}  
</ul>  
</li>  
}  
</ul>  


Is this something people would like in favor of XSLT's? The guys at Sitecore could add some helpers, modelbinders and stuff like that to make MVC even easier (They might be working on it right now), is a LINQ query easier to understand that XPATH?
Would this make Sitecore development even more productive?
I think so, do you?