PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/Framework/NakedObjects.Reflector.DotNet/facets/ordering/memberorder/DeweyOrderSet.cs

http://nakedobjects.codeplex.com
C# | 146 lines | 72 code | 14 blank | 60 comment | 9 complexity | 731aadf72a6e953eca75b295bd49d17a MD5 | raw file
  1. // Copyright Š Naked Objects Group Ltd ( http://www.nakedobjects.net).
  2. // All Rights Reserved. This code released under the terms of the
  3. // Microsoft Public License (MS-PL) ( http://opensource.org/licenses/ms-pl.html)
  4. using System.Collections.Generic;
  5. using NakedObjects.Architecture.Facets.Ordering.MemberOrder;
  6. using NakedObjects.Reflector.Peer;
  7. namespace NakedObjects.Reflector.DotNet.Facets.Ordering.MemberOrder {
  8. /// <summary>
  9. /// Represents a nested hierarchy of ordered members.
  10. /// </summary>
  11. /// <para>
  12. /// At each level the elements are either <see cref="INakedObjectMemberPeer"/>s or they are
  13. /// instances of <see cref="OrderSet"/> represent a group of <see cref="INakedObjectMemberPeer"/>s that
  14. /// have a <see cref="IMemberOrderFacet"/> of the same name.
  15. /// </para>
  16. /// <para>
  17. /// With no name, (ie <c>name=""</c> is the default), at the top level
  18. /// </para>
  19. /// <code>
  20. /// MemberOrder(sequence="1")
  21. /// MemberOrder(sequence="1.1")
  22. /// MemberOrder(sequence="1.2")
  23. /// MemberOrder(sequence="1.2.1")
  24. /// MemberOrder(sequence="1.3")
  25. /// </code>
  26. ///
  27. /// <para>
  28. /// With names, creates a hierarchy.
  29. /// </para>
  30. ///
  31. /// <code>
  32. /// MemberOrder(sequence="1.1") // no parent
  33. /// MemberOrder(sequence="1.2.1")
  34. /// MemberOrder(sequence="1.3")
  35. /// MemberOrder(name="abc", sequence="1") // group is abc, parent is ""
  36. /// MemberOrder(name="abc", sequence="1.2")
  37. /// MemberOrder(name="abc,def", sequence="1") // group is def, parent is abc
  38. /// MemberOrder(name="abc,def", sequence="1.2")
  39. /// </code>
  40. public class DeweyOrderSet : OrderSet {
  41. private DeweyOrderSet(string groupName)
  42. : base(groupName) {}
  43. public static DeweyOrderSet CreateOrderSet(INakedObjectMemberPeer[] members) {
  44. var sortedMembersByGroup = new SortedList<string, List<INakedObjectMemberPeer>>();
  45. var nonAnnotatedGroup = new List<INakedObjectMemberPeer>();
  46. // spin over all the members and put them into a Map of SortedSets
  47. // any non-annotated members go into additional nonAnnotatedGroup set.
  48. foreach (INakedObjectMemberPeer member in members) {
  49. var memberOrder = member.GetFacet<IMemberOrderFacet>();
  50. if (memberOrder != null) {
  51. List<INakedObjectMemberPeer> sortedMembersForGroup = GetSortedSet(sortedMembersByGroup, memberOrder.Name);
  52. sortedMembersForGroup.Add(member);
  53. }
  54. else {
  55. nonAnnotatedGroup.Add(member);
  56. }
  57. }
  58. nonAnnotatedGroup.Sort(new MemberIdentifierComparator());
  59. foreach (var list in sortedMembersByGroup.Values) {
  60. list.Sort(new MemberOrderComparator(true));
  61. }
  62. // add the non-annotated group to the first "" group.
  63. IList<INakedObjectMemberPeer> defaultSet = GetSortedSet(sortedMembersByGroup, "");
  64. foreach (INakedObjectMemberPeer member in nonAnnotatedGroup) {
  65. defaultSet.Add(member);
  66. }
  67. // create OrderSets, wiring up parents and children.
  68. // since sortedMembersByGroup is a SortedMap, the
  69. // iteration will be in alphabetical order (ie parent groups before their children).
  70. ICollection<string> groupNames = sortedMembersByGroup.Keys;
  71. IDictionary<string, DeweyOrderSet> orderSetsByGroup = new SortedList<string, DeweyOrderSet>();
  72. foreach (string groupName in groupNames) {
  73. var deweyOrderSet = new DeweyOrderSet(groupName);
  74. orderSetsByGroup.Add(groupName, deweyOrderSet);
  75. EnsureParentFor(orderSetsByGroup, deweyOrderSet);
  76. }
  77. // now populate the OrderSets
  78. foreach (string groupName in groupNames) {
  79. DeweyOrderSet deweyOrderSet = orderSetsByGroup[groupName];
  80. IList<INakedObjectMemberPeer> sortedMembers = sortedMembersByGroup[groupName];
  81. foreach (INakedObjectMemberPeer ordeableElement in sortedMembers) {
  82. deweyOrderSet.AddElement(ordeableElement);
  83. }
  84. deweyOrderSet.CopyOverChildren();
  85. }
  86. return orderSetsByGroup[""];
  87. }
  88. /// <summary>
  89. /// Recursively creates parents all the way up to root (<c>""</c>),
  90. /// along the way associating each child with its parent and adding
  91. /// the child as an element of its parent.
  92. /// </summary>
  93. private static void EnsureParentFor(IDictionary<string, DeweyOrderSet> orderSetsByGroup, DeweyOrderSet deweyOrderSet) {
  94. string parentGroup = deweyOrderSet.GroupPath;
  95. DeweyOrderSet parentOrderSet = orderSetsByGroup[parentGroup];
  96. if (parentOrderSet == null) {
  97. parentOrderSet = new DeweyOrderSet(parentGroup);
  98. orderSetsByGroup[parentGroup] = parentOrderSet;
  99. if (!parentGroup.Equals("")) {
  100. EnsureParentFor(orderSetsByGroup, deweyOrderSet);
  101. }
  102. }
  103. // check in case at root
  104. if (deweyOrderSet != parentOrderSet) {
  105. deweyOrderSet.Parent = parentOrderSet;
  106. parentOrderSet.AddChild(deweyOrderSet);
  107. }
  108. }
  109. /// <summary>
  110. /// Gets the SortedSet with the specified group from the supplied Map of SortedSets.
  111. /// </summary>
  112. /// <para>
  113. /// If there is no such SortedSet, creates.
  114. /// </para>
  115. private static List<INakedObjectMemberPeer> GetSortedSet(IDictionary<string, List<INakedObjectMemberPeer>> sortedMembersByGroup,
  116. string groupName) {
  117. if (!sortedMembersByGroup.ContainsKey(groupName)) {
  118. sortedMembersByGroup[groupName] = new List<INakedObjectMemberPeer>(); // (new MemberOrderComparator(true));
  119. }
  120. return sortedMembersByGroup[groupName];
  121. }
  122. /// <summary>
  123. /// Format is: <c>abc,def:XXel/YYm/ZZch</c>
  124. /// Where <c>abc,def</c> is group name,
  125. /// <c>XX</c> is number of elements, <c>YY</c> is number of members, and
  126. /// <c>ZZ</c> is number of child order sets.
  127. /// </summary>
  128. public override string ToString() {
  129. return GroupFullName + ":" + Size() + "el/" + (Size() - Children.Count) + "m/" + Children.Count + "ch";
  130. }
  131. }
  132. }