SmartAPI
Open Source .NET RQL library for RedDot CMS / OpenText WSM Management Server
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
IContentClassPreassignable.cs
Go to the documentation of this file.
1 ï»¿// SmartAPI - .Net programmatic access to RedDot servers
2 //
3 // Copyright (C) 2013 erminas GbR
4 //
5 // This program is free software: you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free Software Foundation,
7 // either version 3 of the License, or (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 // See the GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License along with this program.
14 // If not, see <http://www.gnu.org/licenses/>.
15 
16 using System;
17 using System.Collections;
18 using System.Collections.Generic;
19 using System.Linq;
20 using System.Xml;
21 using erminas.SmartAPI.Exceptions;
22 using erminas.SmartAPI.Utils;
23 using erminas.SmartAPI.Utils.CachedCollections;
24 
25 namespace erminas.SmartAPI.CMS.Project.ContentClasses.Elements
26 {
28  {
29  PreassignedContentClassesAndPageDefinitions PreassignedContentClasses { get; }
30  }
31 
33  {
35 
36  private List<IContentClass> _contentClasses;
37  private bool _isDirty = true;
38  private List<IPageDefinition> _pageDefinitions;
39 
41  {
42  Element = element;
43  var contentClassModifier = new Modifier<IContentClass>(GetContentClasses,
44  contentClasses =>
45  Set(contentClasses, PageDefinitions), Add, Remove);
46  ContentClasses = new Preassigned<IContentClass>(contentClassModifier);
47 
48  var pageDefinitionModifier = new Modifier<IPageDefinition>(GetPageDefinitions,
49  pageDefinitions =>
50  Set(ContentClasses, pageDefinitions), Add, Remove);
51  PageDefinitions = new Preassigned<IPageDefinition>(pageDefinitionModifier);
52  }
53 
54  public Preassigned<IContentClass> ContentClasses { get; private set; }
55 
56  public void InvalidateCache()
57  {
58  _isDirty = true;
59  }
60 
61  public Preassigned<IPageDefinition> PageDefinitions { get; private set; }
62 
63  public void Refresh()
64  {
65  XmlNodeList contentClasses, pageDefinitions;
66  ExecuteLoadQuery(out contentClasses, out pageDefinitions);
67 
68  _contentClasses = ExtractContentClasses(contentClasses);
69  _pageDefinitions = ExtractPageDefinitions(pageDefinitions);
70  }
71 
72  public void Set(IEnumerable<IContentClass> contentClasses, IEnumerable<IPageDefinition> pageDefinitions)
73  {
74  var assignmentQuery = ToAssignmentQuery(contentClasses, pageDefinitions);
75  ExecuteAssignmentQuery(assignmentQuery);
76 
77  InvalidateCache();
78  }
79 
80  private void Add(IPageDefinition pageDefinition)
81  {
82  Set(ContentClasses, PageDefinitions.Union(new[] {pageDefinition}));
83  }
84 
85  private void Add(IContentClass contentClass)
86  {
87  Set(ContentClasses.Union(new List<IContentClass> {contentClass}), PageDefinitions);
88  }
89 
90  private void ExecuteAssignmentQuery(string assignmentQuery)
91  {
92  var xmlDoc = Element.ContentClass.Project.ExecuteRQL(assignmentQuery);
93 
94  if (!xmlDoc.IsContainingOk())
95  {
96  throw new SmartAPIException(Element.Session.ServerLogin,
97  string.Format("Could not set presassigned content classes for {0}", Element));
98  }
99  }
100 
101  private void ExecuteLoadQuery(out XmlNodeList contentClasses, out XmlNodeList pageDefinitions)
102  {
103  const string LOAD_PREASSIGNMENT =
104  @"<TEMPLATELIST action=""load"" linkguid=""{0}"" assigntemplates=""1"" withpagedefinitions=""1""/>";
105 
106  var xmlDoc = Element.ContentClass.Project.ExecuteRQL(LOAD_PREASSIGNMENT.RQLFormat(Element));
107  contentClasses = xmlDoc.SelectNodes("//TEMPLATE[@selectinnewpage='1']");
108  pageDefinitions = xmlDoc.SelectNodes("//PAGEDEFINITION[@selectinnewpage='1']");
109  }
110 
111  private List<IContentClass> ExtractContentClasses(XmlNodeList contentClasses)
112  {
113  return (from XmlElement curContentClass in contentClasses
114  select
115  (IContentClass)
116  new ContentClass(Element.ContentClass.Project, curContentClass.GetGuid())
117  {
118  Name = curContentClass.GetName(),
119  DescriptionInCurrentDisplayLanguage = curContentClass.GetAttributeValue("description")
120  })
121  .ToList();
122  }
123 
124  private List<IPageDefinition> ExtractPageDefinitions(XmlNodeList pageDefinitions)
125  {
126  return (from XmlElement curPageDefinition in pageDefinitions
127  select
128  new PageDefinition(
129  new ContentClass(Element.ContentClass.Project, curPageDefinition.GetGuid("templateguid")),
130  curPageDefinition)).Cast<IPageDefinition>().ToList();
131  }
132 
133  private IEnumerable<IContentClass> GetContentClasses()
134  {
135  if (_isDirty)
136  {
137  Refresh();
138  }
139  return _contentClasses;
140  }
141 
142  private IEnumerable<IPageDefinition> GetPageDefinitions()
143  {
144  if (_isDirty)
145  {
146  Refresh();
147  }
148  return _pageDefinitions;
149  }
150 
151  private void Remove(IContentClass contentClass)
152  {
153  Set(ContentClasses.Except(new[] {contentClass}), PageDefinitions);
154  }
155 
156  private void Remove(IPageDefinition pageDefinition)
157  {
158  Set(ContentClasses, PageDefinitions.Except(new[] {pageDefinition}));
159  }
160 
161  private string ToAssignmentQuery(IEnumerable<IContentClass> contentClasses,
162  IEnumerable<IPageDefinition> pageDefinitions)
163  {
164  contentClasses = contentClasses ?? new List<IContentClass>();
165  pageDefinitions = pageDefinitions ?? new List<IPageDefinition>();
166 
167  const string SINGLE_PREASSIGNMENT = @"<TEMPLATE guid=""{0}""/>";
168 
169  string assignments = contentClasses.Cast<IRedDotObject>()
170  .Union(pageDefinitions)
171  .Aggregate("", (s, o) => s + SINGLE_PREASSIGNMENT.RQLFormat(o));
172 
173  const string SET_PREASSIGNMENT_ENVELOPE =
174  @"<TEMPLATE><ELEMENT action=""assign"" guid=""{0}""><TEMPLATES extendedrestriction=""{1}"">{2}</TEMPLATES></ELEMENT></TEMPLATE>";
175  string assignmentQuery = SET_PREASSIGNMENT_ENVELOPE.RQLFormat(Element, false, assignments);
176  return assignmentQuery;
177  }
178 
179  //Also apply this restriction to connecting existing pages
180  internal class Modifier<T> where T : IRedDotObject
181  {
182  internal readonly Action<T> Add;
183  internal readonly Func<IEnumerable<T>> Get;
184  internal readonly Action<T> Remove;
185  internal readonly Action<IEnumerable<T>> Set;
186 
187  internal Modifier(Func<IEnumerable<T>> get, Action<IEnumerable<T>> set, Action<T> add, Action<T> remove)
188  {
189  Get = get;
190  Set = set;
191  Add = add;
192  Remove = remove;
193  }
194  }
195  }
196 
197  public class Preassigned<T> : IEnumerable<T> where T : IRedDotObject
198  {
199  private readonly PreassignedContentClassesAndPageDefinitions.Modifier<T> _parent;
200 
201  internal Preassigned(PreassignedContentClassesAndPageDefinitions.Modifier<T> parent)
202  {
203  _parent = parent;
204  }
205 
206  public void Add(T element)
207  {
208  _parent.Add(element);
209  }
210 
211  public IEnumerator<T> GetEnumerator()
212  {
213  return _parent.Get().GetEnumerator();
214  }
215 
216  public void Remove(T element)
217  {
218  _parent.Remove(element);
219  }
220 
221  public void Set(IEnumerable<T> elements)
222  {
223  _parent.Set(elements);
224  }
225 
226  IEnumerator IEnumerable.GetEnumerator()
227  {
228  return _parent.Get().GetEnumerator();
229  }
230  }
231 }