Showing posts with label template. Show all posts
Showing posts with label template. 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.