SmartAPI
Open Source .NET RQL library for RedDot CMS / OpenText WSM Management Server
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
ILinkConnections.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.Xml;
20 using erminas.SmartAPI.Utils;
21 using erminas.SmartAPI.Utils.CachedCollections;
22 
23 namespace erminas.SmartAPI.CMS.Project.Pages.Elements
24 {
25  public enum Linking
26  {
27  AsConnection,
28  AsReference
29  }
30 
31  internal class LinkConnections : RDList<IPage>, ILinkConnections
32  {
33  private readonly ILinkElement _element;
34  private bool _isNeedingRefresh;
35 
36  protected internal LinkConnections(ILinkElement element, Caching caching) : base(caching)
37  {
38  _element = element;
39  RetrieveFunc = GetConnectedPages;
40  }
41 
42  public void Clear()
43  {
44  if (IsReferencing)
45  {
46  SetReference(null);
47  }
48  else
49  {
50  RemoveRange(this);
51  }
52  }
53 
54  public void Connect(IPage page)
55  {
56  SaveConnection(page);
57  }
58 
59  public bool IsReference
60  {
61  get { return _element.LinkType == LinkType.Reference; }
62  }
63 
64  public bool IsReferencing
65  {
66  get { return LinkType == LinkType.Reference; }
67  }
68 
69  public LinkType LinkType
70  {
71  get
72  {
73  if (_isNeedingRefresh)
74  {
75  _element.Refresh();
76  _isNeedingRefresh = false;
77  }
78  return _element.LinkType;
79  }
80  }
81 
82  public IProject Project
83  {
84  get { return _element.Project; }
85  }
86 
87  public ILinkTarget Reference
88  {
89  get { throw new NotImplementedException(); }
90  set { SetReference(value); }
91  }
92 
93  public void Remove(IPage page)
94  {
95  RemoveRange(new[] {page});
96  }
97 
98  public ISession Session
99  {
100  get { return _element.Session; }
101  }
102 
103  public virtual void Set(ILinkTarget target, Linking linking)
104  {
105  if (linking == Linking.AsReference)
106  {
107  Reference = target;
108  }
109  else
110  {
111  SaveConnection((IPage) target);
112  }
113  }
114 
115  protected void RemoveRange(IEnumerable<IPage> pages)
116  {
117  const string DISCONNECT_PAGES = @"<LINK action=""save"" guid=""{0}""><PAGES>{1}</PAGES></LINK>";
118  const string SINGLE_PAGE = @"<PAGE deleted=""1"" guid=""{0}"" />";
119 
120  var pagesStr = pages.Aggregate("", (x, page) => x + string.Format(SINGLE_PAGE, (page.Guid).ToRQLString()));
121  Project.ExecuteRQL(DISCONNECT_PAGES.RQLFormat(_element, pagesStr));
122  InvalidateCache();
123  }
124 
125  protected void SaveConnection(IPage page)
126  {
127  const string CONNECT_PREPARE =
128  @"<LINK action=""save"" reddotcacheguid="""" guid=""{0}"" value=""" + RQL.SESSIONKEY_PLACEHOLDER +
129  @""" />";
130 
131  Project.ExecuteRQL(CONNECT_PREPARE.RQLFormat(_element));
132 
133  const string CONNECT =
134  @"<LINKSFROM action=""save"" pageid="""" pageguid=""{0}"" reddotcacheguid=""""><LINK guid=""{1}""/></LINKSFROM>";
135 
136  Project.ExecuteRQL(CONNECT.RQLFormat(page, _element));
137 
138  InvalidateCache();
139  if (LinkType == LinkType.Reference)
140  {
141  _isNeedingRefresh = true;
142  }
143  }
144 
145  private List<IPage> GetConnectedPages()
146  {
147  const string LIST_LINKED_PAGES = @"<LINK guid=""{0}""><PAGES action=""list"" /></LINK>";
148  var xmlDoc = Project.ExecuteRQL(LIST_LINKED_PAGES.RQLFormat(_element));
149  return (from XmlElement curPage in xmlDoc.GetElementsByTagName("PAGE")
150  let page =
151  (IPage)
152  new Page(Project, curPage.GetGuid(), _element.LanguageVariant)
153  {
154  Id = curPage.GetIntAttributeValue("id").GetValueOrDefault(),
155  InitialHeadlineValue = curPage.GetAttributeValue("headline")
156  }
157  select page).ToList();
158  }
159 
160  private void ReferenceElement(ILinkElement element)
161  {
162  const string LINK_TO_ELEMENT =
163  @"<PAGE><LINK action=""assign"" guid=""{0}""><LINK guid=""{1}"" /></LINK></PAGE>";
164  //we can't really check the success, because an empty iodata element is returned on success as on (at least some) errors
165  Project.ExecuteRQL(LINK_TO_ELEMENT.RQLFormat(_element, element));
166 
167  InvalidateCache();
168  if (LinkType != LinkType.Reference)
169  {
170  _isNeedingRefresh = true;
171  }
172  }
173 
174  private void ReferencePage(IPage target)
175  {
176  const string LINK_TO_PAGE =
177  @"<PAGE><LINK action=""reference"" guid=""{0}""><PAGE guid=""{1}"" /></LINK></PAGE>";
178  //we can't really check the success, because an empty iodata element is returned on success as on (at least some) errors
179  Project.ExecuteRQL(LINK_TO_PAGE.RQLFormat(_element, target));
180 
181  InvalidateCache();
182  if (LinkType != LinkType.Reference)
183  {
184  _isNeedingRefresh = true;
185  }
186  }
187 
188  private void SetReference(ILinkTarget target)
189  {
190  if (target == null)
191  {
192  UnlinkReference();
193  }
194  else
195  {
196  if (target is IPage)
197  {
198  ReferencePage((IPage) target);
199  }
200  else
201  {
202  ReferenceElement((ILinkElement) target);
203  }
204  }
205  }
206 
207  private void UnlinkReference()
208  {
209  const string UNLINK_ELEMENT =
210  @"<LINK guid=""{0}""><LINK action=""unlink"" reddotcacheguid=""""/><URL action=""unlink""/></LINK>";
211  //we can't really check the success, because an empty iodata element is returned on success as on (at least some) errors
212  Project.ExecuteRQL(UNLINK_ELEMENT.RQLFormat(_element));
213 
214  InvalidateCache();
215  _isNeedingRefresh = true;
216  }
217  }
218 
219  public interface ILinkConnections : IRDList<IPage>, IProjectObject
220  {
221  void Clear();
222  void Connect(IPage page);
223 
224  bool IsReferencing { get; }
226  ILinkTarget Reference { get; set; }
227  void Remove(IPage page);
228  void Set(ILinkTarget linkTarget, Linking linkingType);
229  }
230 }