SmartAPI
Open Source .NET RQL library for RedDot CMS / OpenText WSM Management Server
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
IPages.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.Generic;
18 using System.Linq;
19 using System.Web;
20 using System.Xml;
21 using erminas.SmartAPI.CMS.Project.ContentClasses;
22 using erminas.SmartAPI.Exceptions;
23 using erminas.SmartAPI.Utils;
24 using erminas.SmartAPI.Utils.CachedCollections;
25 
26 namespace erminas.SmartAPI.CMS.Project.Pages
27 {
28  public interface IStartPagesValue : ILanguageDependentReadValue<IIndexedRDList<string, IPage>>, ICached
29  {
30 
31  }
32 
33  public interface IPages
34  {
40  IndexedRDList<int, IPage> this[string language] { get; }
41 
48  IndexedRDList<int, IPage> OfCurrentLanguage { get; }
49 
50  IStartPagesValue StartPages { get; }
51 
56  IPage GetByGuid(Guid pageGuid, ILanguageVariant languageVariant);
57 
62  bool TryGetByGuid(Guid pageGuid, ILanguageVariant languageVariant, out IPage page);
63 
70  IPage Create(IContentClass cc, string headline = null);
71 
79  IPage CreateAndConnect(IContentClass cc, Guid linkGuid, string headline = null);
80 
85  IExtendedPageSearch CreateExtendedSearch();
86 
91  IPageSearch CreateSearch();
92 
103  IEnumerable<IPage> Search(Action<IPageSearch> configurator = null);
104 
124  List<ResultGroup> SearchExtended(Action<IExtendedPageSearch> configurator = null);
125  }
126 
127  public class Pages : IPages
128  {
129  private readonly Dictionary<string, IndexedRDList<int, IPage>> _pagesByLanguage =
130  new Dictionary<string, IndexedRDList<int, IPage>>();
131 
132  private readonly IProject _project;
133  private readonly IStartPagesValue _startPage;
134 
135  public Pages(IProject project)
136  {
137  _project = project;
138  _startPage = new StartPagesValue(project);
139  }
140 
141  public IStartPagesValue StartPages
142  {
143  get { return _startPage; }
144  }
145 
146  public IPage GetByGuid(Guid pageGuid, ILanguageVariant languageVariant)
147  {
148  return new Page(_project, pageGuid, languageVariant).Refreshed();
149  }
150 
151  public bool TryGetByGuid(Guid pageGuid, ILanguageVariant languageVariant, out IPage page)
152  {
153  try
154  {
155  page = GetByGuid(pageGuid, languageVariant);
156  return true;
157  }
158  catch (SmartAPIException)
159  {
160  page = null;
161  return false;
162  }
163  }
164 
171  public IPage Create(IContentClass cc, string headline = null)
172  {
173  XmlDocument xmlDoc = _project.ExecuteRQL(PageCreationString(cc, headline));
174  return CreatePageFromCreationReply(xmlDoc);
175  }
176 
184  public IPage CreateAndConnect(IContentClass cc, Guid linkGuid, string headline = null)
185  {
186  const string CREATE_AND_LINK_PAGE = @"<LINK action=""assign"" guid=""{0}"">{1}</LINK>";
187  XmlDocument xmlDoc =
188  _project.ExecuteRQL(string.Format(CREATE_AND_LINK_PAGE, linkGuid.ToRQLString(), PageCreationString(cc, headline)));
189  return CreatePageFromCreationReply(xmlDoc);
190  }
191 
196  public IExtendedPageSearch CreateExtendedSearch()
197  {
198  return new ExtendedPageSearch(_project);
199  }
200 
205  public IPageSearch CreateSearch()
206  {
207  return new PageSearch(_project);
208  }
209 
213  public IndexedRDList<int, IPage> this[string language]
214  {
215  get { return GetPagesForLanguageVariant(language); }
216  }
217 
221  public IndexedRDList<int, IPage> OfCurrentLanguage
222  {
223  get { return GetPagesForLanguageVariant(_project.LanguageVariants.Current.Abbreviation); }
224  }
225 
236  public IEnumerable<IPage> Search(Action<IPageSearch> configurator = null)
237  {
238  var search = new PageSearch(_project);
239  if (configurator != null)
240  {
241  configurator(search);
242  }
243 
244  return search.Execute();
245  }
246 
266  public List<ResultGroup> SearchExtended(Action<IExtendedPageSearch> configurator = null)
267  {
268  var search = new ExtendedPageSearch(_project);
269  if (configurator != null)
270  {
271  configurator(search);
272  }
273 
274  return search.Execute();
275  }
276 
277  private IPage CreatePageFromCreationReply(XmlDocument xmlDoc)
278  {
279  try
280  {
281  var pageItem = (XmlElement) xmlDoc.GetElementsByTagName("PAGE")[0];
282  return new Page(_project, pageItem);
283  }
284  catch (Exception e)
285  {
286  throw new SmartAPIException(_project.Session.ServerLogin, "Could not create page", e);
287  }
288  }
289 
290  private List<IPage> GetPages()
291  {
292  const string LIST_PAGES = @"<PROJECT><PAGES action=""list""/></PROJECT>";
293  XmlDocument xmlDoc = _project.ExecuteRQL(LIST_PAGES);
294  return (from XmlElement curPage in xmlDoc.GetElementsByTagName("PAGE")
295  select (IPage) new Page(_project, curPage.GetGuid(), _project.LanguageVariants.Current)
296  {
297  InitialHeadlineValue = curPage.GetAttributeValue("headline"),
298  Id = curPage.GetIntAttributeValue("id")
299  .GetValueOrDefault()
300  }).ToList();
301  }
302 
303  private IndexedRDList<int, IPage> GetPagesForLanguageVariant(string language)
304  {
305  ILanguageVariant languageVariant = _project.LanguageVariants[language];
306  using (new LanguageContext(languageVariant))
307  {
308  return _pagesByLanguage.GetOrAdd(
309  language,
310  () => new IndexedRDList<int, IPage>(
311  () =>
312  {
313  using (new LanguageContext(languageVariant))
314  {
315  return GetPages();
316  }
317  },
318  x => x.Id,
319  Caching.Enabled));
320  }
321  }
322 
323  private static string PageCreationString(IContentClass cc, string headline = null)
324  {
325  const string PAGE_CREATION_STRING = @"<PAGE action=""addnew"" templateguid=""{0}"" {1}/>";
326 
327  string headlineString = headline == null ? "" : string.Format(@"headline=""{0}""", HttpUtility.HtmlEncode(headline));
328  return string.Format(PAGE_CREATION_STRING, cc.Guid.ToRQLString(), headlineString);
329  }
330 
331 
332  }
333 
334  internal class StartPagesValue : IStartPagesValue
335  {
336  private readonly IProject _project;
337  private readonly Dictionary<ILanguageVariant, IIndexedRDList<string, IPage>> _startPagesByLanguageVariant = new Dictionary<ILanguageVariant, IIndexedRDList<string, IPage>>();
338  private Guid[] _startPageGuids;
339 
340  public StartPagesValue(IProject project)
341  {
342  _project = project;
343  }
344 
345  public IPartialRedDotProjectObject Parent
346  {
347  get
348  {
349  throw new InvalidOperationException("StartPage has no parent");
350  }
351  }
352 
353  public IIndexedRDList<string, IPage> ForCurrentLanguage
354  {
355  get { return ((ILanguageDependentReadValue < IIndexedRDList<string, IPage>>)(this))[_project.LanguageVariants.Current]; }
356  }
357 
358  public IIndexedRDList<string, IPage> ForMainLanguage
359  {
360  get { return ((ILanguageDependentReadValue<IIndexedRDList<string, IPage>>)(this))[_project.LanguageVariants.Main]; }
361  }
362 
363  IIndexedRDList<string, IPage> ILanguageDependentReadValue<IIndexedRDList<string, IPage>>.this[ILanguageVariant languageVariant]
364  {
365  get
366  {
367 
368  return _startPagesByLanguageVariant.GetOrAdd(languageVariant, ()=>GetStartPages(languageVariant));//startPageGuids == null ? new IndexedRDList<string, IPage>(()=>new List<IPage>(), x=>x.Headline, Caching.Enabled) : _startPagesByLanguageVariant.GetOrAdd(languageVariant, ()=>GetStartPages(languageVariant));
369  }
370  }
371 
372  IIndexedRDList<string, IPage> ILanguageDependentReadValue<IIndexedRDList<string, IPage>>.this[string languageAbbreviation]
373  {
374  get { return ((ILanguageDependentReadValue<IIndexedRDList<string, IPage>>)(this))[_project.LanguageVariants[languageAbbreviation]]; }
375  }
376 
377  private IIndexedRDList<string, IPage> GetStartPages(ILanguageVariant languageVariant)
378  {
379  return new IndexedRDList<string, IPage>(()=>Refreshed(languageVariant), x=>x.Headline, Caching.Enabled);
380  }
381 
382  private List<IPage> Refreshed(ILanguageVariant languageVariant)
383  {
384  Refresh();
385  return _startPageGuids.Select(x => _project.Pages.GetByGuid(x, languageVariant)).ToList();
386  }
387 
388  private void EnsureInitialization()
389  {
390  if (_startPageGuids == null)
391  {
392  const string LOAD_DINGS = @"<LINK guid=""{0}""><PAGES action=""list"" /></LINK>";
393  var doc = _project.ExecuteRQL(LOAD_DINGS.RQLFormat("00000000000000000000000000000001"));
394 
395  var pageElements = doc.GetElementsByTagName("PAGE");
396  _startPageGuids = pageElements.Cast<XmlElement>()
397  .Select(XmlUtil.GetGuid)
398  .ToArray();
399  }
400  }
401 
402  public void InvalidateCache()
403  {
404  _startPageGuids = null;
405  _startPagesByLanguageVariant.Clear();
406  }
407 
408  public void Refresh()
409  {
410  InvalidateCache();
411  EnsureInitialization();
412  }
413  }
414 }