InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
XMLReferenceGraph.h
1 //========================================================================================
2 //
3 // $File$
4 //
5 // Owner: Mat Marcus
6 //
7 // $Author$
8 //
9 // $DateTime$
10 //
11 // $Revision$
12 //
13 // $Change$
14 //
15 // Copyright 1997-2010 Adobe Systems Incorporated. All rights reserved.
16 //
17 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
18 // with the terms of the Adobe license agreement accompanying it. If you have received
19 // this file from a source other than Adobe, then your use, modification, or
20 // distribution of it requires the prior written permission of Adobe.
21 //
22 //========================================================================================
23 
24 #ifndef __XMLReferenceGraph__
25 #define __XMLReferenceGraph__
26 
27 
28 #include "boost/graph/graph_traits.hpp"
29 #include "boost/iterator/iterator_facade.hpp"
30 #include "boost/iterator_adaptors.hpp"
31 
32 #include "DepthFirstTreeIterator.h"
33 #include "InterfacePtr.h"
34 #include "IIDXMLElement.h"
35 #include "K2Assert.h"
36 
37 
39 {
40 public:
42  fTargetXMLRef(),
43  fTrueParentXMLRef()
44  {}
45 
46  XMLReferenceGraphEdge(const XMLReference& targetXMLRef, const XMLReference& trueParentXMLRef = kInvalidXMLReference) :
47  fTargetXMLRef(targetXMLRef),
48  fTrueParentXMLRef(trueParentXMLRef)
49  {
50  if (fTargetXMLRef != kInvalidXMLReference && fTrueParentXMLRef == kInvalidXMLReference) {
51  // calculate the true parent
52  InterfacePtr<IIDXMLElement> element(fTargetXMLRef.Instantiate());
53  fTrueParentXMLRef = element->GetParent();
54  }
55 
56  ASSERT_MSG(fTargetXMLRef != kInvalidXMLReference || fTrueParentXMLRef != kInvalidXMLReference, "XMLReferenceGraphEdge::XMLReferenceGraphEdge: true parent should be specified when target is kInvalidXMLReference");
57  }
58 
60  fTargetXMLRef(other.fTargetXMLRef),
61  fTrueParentXMLRef(other.fTrueParentXMLRef)
62  {}
63 
64  const XMLReference& GetTargetXMLReference() const { return fTargetXMLRef; }
65 
66  const XMLReference& GetTrueParentXMLReference() const { return fTrueParentXMLRef; }
67 
68  bool16 operator==(const XMLReferenceGraphEdge& copy) const
69  {
70  return (fTargetXMLRef == copy.fTargetXMLRef && fTrueParentXMLRef == copy.fTrueParentXMLRef) ? kTrue : kFalse;
71  }
72 
73 private:
74  XMLReference fTargetXMLRef; // target XMLReference
75  XMLReference fTrueParentXMLRef; // true parent of target, not necessarily the same as source()
76 };
77 
78 
79 #if 0
80 struct XMLReferenceIteratorPolicies : public boost::default_iterator_policies
81 {
82  XMLReferenceIteratorPolicies() {}
83 
84  template <class IteratorAdaptor>
85  typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
86  { return x.base(); }
87 
88  template <class IteratorAdaptor>
89  void increment(IteratorAdaptor& x) { advance(x, 1); }
90 
91  //template <class IteratorAdaptor>
92  //void decrement(IteratorAdaptor& x) { advance(x, -1); }
93 
94  template <class IteratorAdaptor, class DifferenceType>
95  void advance(IteratorAdaptor& x, DifferenceType n);
96 
97 private:
98  template <class IteratorAdaptor>
99  XMLReference GetParentRef(IteratorAdaptor& x);
100 };
101 
102 template <class IteratorAdaptor, class DifferenceType>
103 void XMLReferenceIteratorPolicies::advance(IteratorAdaptor& x, DifferenceType n)
104 {
105  ASSERT_MSG(n==1, "XMLReferenceIteratorPolicies::advance: only single step forward iterator for now");
106  ASSERT_MSG(x.base().GetTargetXMLReference() != kInvalidXMLReference, "XMLReferenceIteratorPolicies::advance: cannot advance kInvalidXMLReference");
107  if (x.base().GetTargetXMLReference() != kInvalidXMLReference)
108  {
109  InterfacePtr<IIDXMLElement> parent(GetParentRef(x).Instantiate());
110  int32 index = parent->FindChild(x.base().GetTargetXMLReference()) + n;
111  ASSERT(index <= parent->GetChildCount());
112  x.base() = (index >= parent->GetChildCount()) ? XMLReferenceGraphEdge(kInvalidXMLReference, parent->GetXMLReference()) : XMLReferenceGraphEdge(parent->GetNthChild(index));
113  }
114 }
115 
116 template <class IteratorAdaptor>
117 XMLReference XMLReferenceIteratorPolicies::GetParentRef(IteratorAdaptor& x)
118 {
119  return (x.base().GetTargetXMLReference() != kInvalidXMLReference) ? InterfacePtr<IIDXMLElement> (x.base().GetTargetXMLReference().Instantiate())->GetParent() : x.base().GetTrueParentXMLReference();
120 }
121 #endif
122 
123 
124 
129 class XMLReferenceIterator : public boost::iterator_facade<
130  XMLReferenceIterator, // derived
131  XMLReferenceGraphEdge, // value
132  boost::forward_traversal_tag, // category
133  XMLReferenceGraphEdge, // reference
134  int32 // difference
135  >
136 {
137 public:
139  fData()
140  {}
141 
142  explicit XMLReferenceIterator(const XMLReferenceGraphEdge& other) :
143  fData(other)
144  {}
145 
146 private:
147  friend class boost::iterator_core_access;
148 
149  void increment()
150  {
151  advance(1);
152  }
153 
154  bool equal(XMLReferenceIterator const& other) const { return (fData == other.fData); }
155 
156  // |||WLin 6/12/2005: the default prototype for dereference() doesn't seem right. You'd be
157  // returning a non-const reference to a member data but yet the method is const. This may
158  // work with pointers but that seems to be easier to deal with using const_cast. For
159  // objects to work it takes more. Currently no clients are making non-const calls from the
160  // return value of this method, so I made the return value const. If this changes, then
161  // we'll have to make a different change instead, either make this method non-const or the
162  // member data mutable (yuck)
163 // XMLReferenceGraphEdge& dereference() const { return reinterpret_cast<XMLReferenceGraphEdge>(fData); }
164  const XMLReferenceGraphEdge& dereference() const { return fData; }
165 
166  void advance(int32 n)
167  {
168  ASSERT_MSG(n >= 0, "XMLReferenceIterator::advance: only positive increments are supported right now");
169  ASSERT_MSG(n == 1, "XMLReferenceIterator::advance: warning: only single increment is implemented. large advances are done in a loop and may be inefficient");
170  ASSERT_MSG(fData.GetTargetXMLReference() != kInvalidXMLReference, "XMLReferenceIterator::advance: cannot advance kInvalidXMLReference");
171  while (--n >= 0 && fData.GetTargetXMLReference() != kInvalidXMLReference) {
172  InterfacePtr<IIDXMLElement> parent(GetParentXMLRef().Instantiate());
173  int32 index(parent->FindChild(fData.GetTargetXMLReference())+1);
174  ASSERT(index <= parent->GetChildCount());
175  fData = (index >= parent->GetChildCount()) ? XMLReferenceGraphEdge(kInvalidXMLReference, parent->GetXMLReference()) : XMLReferenceGraphEdge(parent->GetNthChild(index));
176  }
177  }
178 
179  XMLReference GetParentXMLRef() const
180  {
181  return (fData.GetTargetXMLReference() != kInvalidXMLReference) ? InterfacePtr<IIDXMLElement> (fData.GetTargetXMLReference().Instantiate())->GetParent() : fData.GetTrueParentXMLReference();
182  }
183 
184  XMLReferenceGraphEdge fData;
185 };
186 
187 #if 0
188 struct XMLInEdgeIteratorPolicies : public boost::default_iterator_policies
189 {
190  XMLInEdgeIteratorPolicies() {}
191 
192  template <class IteratorAdaptor>
193  typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
194  { return x.base(); }
195 
196  template <class IteratorAdaptor>
197  void increment(IteratorAdaptor& x) { advance(x, 1); }
198 
199  //template <class IteratorAdaptor>
200  //void decrement(IteratorAdaptor& x) { advance(x, -1); }
201 
202  template <class IteratorAdaptor, class DifferenceType>
203  void advance(IteratorAdaptor& x, DifferenceType n);
204 };
205 
206 template <class IteratorAdaptor, class DifferenceType>
207 void XMLInEdgeIteratorPolicies::advance(IteratorAdaptor& x, DifferenceType n)
208 {
209  x.base() = XMLReferenceGraphEdge(x.base().GetTrueParentXMLReference(), kInvalidXMLReference);
210 }
211 #endif
212 
213 
214 
218 class XMLInEdgeIterator : public boost::iterator_facade<
219  XMLInEdgeIterator, //derived
220  XMLReferenceGraphEdge, //value
221  boost::forward_traversal_tag, // category
222  XMLReferenceGraphEdge, // reference
223  int32 // difference
224  >
225 {
226 public:
227  XMLInEdgeIterator() :
228  fData()
229  {}
230 
231  explicit XMLInEdgeIterator(const XMLReferenceGraphEdge& other) :
232  fData(other)
233  {}
234 
235 private:
236  friend class boost::iterator_core_access;
237 
238  void increment()
239  {
240  advance(1);
241  }
242 
243  bool equal(XMLInEdgeIterator const& other) const { return (fData == other.fData); }
244 
245  // |||WLin 6/12/2005: the default prototype for dereference() doesn't seem right. You'd be
246  // returning a non-const reference to a member data but yet the method is const. This may
247  // work with pointers but that seems to be easier to deal with using const_cast. For
248  // objects to work it takes more. Currently no clients are making non-const calls from the
249  // return value of this method, so I made the return value const. If this changes, then
250  // we'll have to make a different change instead, either make this method non-const or the
251  // member data mutable (yuck)
252  // XMLReferenceGraphEdge& dereference() const { return reinterpret_cast<XMLReferenceGraphEdge>(fData); }
253  const XMLReferenceGraphEdge& dereference() const { return fData; }
254 
255  void advance(int32 n)
256  {
257  ASSERT_MSG(n >= 0, "XMLInEdgeIterator::advance: only positive increments are supported right now");
258  ASSERT_MSG(fData.GetTargetXMLReference() != kInvalidXMLReference, "XMLInEdgeIterator::advance: cannot advance past end iterator");
259  while (--n >= 0 && fData.GetTargetXMLReference() != kInvalidXMLReference) {
260  fData = XMLReferenceGraphEdge(fData.GetTrueParentXMLReference(), kInvalidXMLReference);
261  ASSERT_MSG(n == 0 || fData.GetTargetXMLReference() != kInvalidXMLReference, "XMLInEdgeIterator::advance: cannot advance past end iterator");
262  }
263  }
264 
265  // member data
266  XMLReferenceGraphEdge fData;
267 };
268 
269 
271 
272  XMLReferenceGraph(const XMLReference& rootVertex = kInvalidXMLReference,
273  const XMLReference& preorderEndEdge = kInvalidXMLReference)
274  : fRootVertex(rootVertex), fPreorderEndEdge(preorderEndEdge) {}
275  const XMLReference& RootVertex() const {return fRootVertex; }
276  const XMLReference& PreorderEndEdge() const {return fPreorderEndEdge; }
277 private:
278  XMLReference fRootVertex;
279  XMLReference fPreorderEndEdge;
280 };
281 
282 
283 namespace boost {
284 template<>
285 struct graph_traits<XMLReferenceGraph> {
288  typedef void adjacency_iterator;
291  typedef void edge_iterator;
292  typedef void vertex_iterator;
293  typedef int32 degree_size_type;
294  typedef int32 vertices_size_type;
295  typedef int32 edges_size_type;
296  typedef boost::directed_tag directed_category;
297  typedef boost::disallow_parallel_edge_tag edge_parallel_category;
298  typedef boost::bidirectional_graph_tag traversal_category;
299 };
300 }
301 
302 typedef boost::graph_traits<XMLReferenceGraph>::out_edge_iterator XMLOutEdgeIterator;
303 
304 
307  std::pair<XMLOutEdgeIterator, XMLOutEdgeIterator>
308 out_edges(boost::graph_traits<XMLReferenceGraph>::vertex_descriptor v, const XMLReferenceGraph& g);
309 
310  boost::graph_traits<XMLReferenceGraph>::degree_size_type
311 out_degree(const XMLReference& v, const XMLReferenceGraph& g);
312 
313  boost::graph_traits<XMLReferenceGraph>::vertex_descriptor
314 source(const boost::graph_traits<XMLReferenceGraph>::edge_descriptor& e, const XMLReferenceGraph& g);
315 
316  boost::graph_traits<XMLReferenceGraph>::vertex_descriptor
317 target(const boost::graph_traits<XMLReferenceGraph>::edge_descriptor& e, const XMLReferenceGraph& g);
318 
321  std::pair<boost::graph_traits<XMLReferenceGraph>::in_edge_iterator, boost::graph_traits<XMLReferenceGraph>::in_edge_iterator>
322 in_edges(boost::graph_traits<XMLReferenceGraph>::vertex_descriptor v, const XMLReferenceGraph& g);
323 
324 // boost::graph_traits<XMLReferenceGraph>::degree_size_type
325 //in_degree(const boost::graph_traits<XMLReferenceGraph>::vertex_descriptor& v, const XMLReferenceGraph& g);
326 
327 // boost::graph_traits<XMLReferenceGraph>::degree_size_type
328 //degree(const boost::graph_traits<XMLReferenceGraph>::vertex_descriptor& v, const XMLReferenceGraph& g);
329 
330 /*
331 boost::graph_traits<XMLReferenceGraph>::vertex_descriptor
332 rootX(const XMLReferenceGraph& g);
333 */
334 
335  XMLOutEdgeIterator
336 incoming_edge(boost::graph_traits<XMLReferenceGraph>::vertex_descriptor v, const XMLReferenceGraph& g);
337 
338 
339 #if 0
340 class XMLDepthFirstTreeIterator: boost::iterator_adaptor<
341  XMLDepthFirstTreeIterator, //derived
342  boost::optional<boost::graph_traits<XMLReferenceGraph>::out_edge_iterator>, // base
343  boost::graph_traits<XMLReferenceGraph>::edge_descriptor, // value
344  boost::forward_traversal_tag, // category
345  boost::graph_traits<XMLReferenceGraph>::edge_descriptor/*&*/, // reference
346  int32 // distance
347  >
348 {
349 public:
350  XMLDepthFirstTreeIterator() :
351  XMLDepthFirstTreeIterator::iterator_adaptor_()
352  {}
353 
354  explicit XMLDepthFirstTreeIterator(const XMLReferenceGraphEdge& other) :
355  XMLDepthFirstTreeIterator::iterator_adaptor_(other)
356  {}
357 
358  XMLReferenceGraphEdge const& base() const { return base(); }
359 
360 private:
361  friend class boost::iterator_core_access;
362 
363  void increment()
364  {
365  ASSERT_FAIL("XMLDepthFirstTreeIterator::increment: not yet implemented");
366  }
367 };
368 #endif
369 
370 
371 class XMLVirtualDepthFirstTreeIterator : public boost::iterator_facade<
372  XMLVirtualDepthFirstTreeIterator, // derived
373  boost::graph_traits<XMLReferenceGraph>::edge_descriptor, // value
374  boost::forward_traversal_tag, // category
375  boost::graph_traits<XMLReferenceGraph>::edge_descriptor/*&*/, // reference
376  int32 // difference
377  >
378 {
379 public:
381  fData()
382  {}
383 
384  explicit XMLVirtualDepthFirstTreeIterator(const boost::graph_traits<XMLReferenceGraph>::edge_descriptor& other) :
385  fData(other)
386  {}
387 
388 private:
389  friend class boost::iterator_core_access;
390 
391  void increment()
392  {
393  advance(1);
394  }
395 
396  bool equal(XMLVirtualDepthFirstTreeIterator const& other) const { return (fData == other.fData); }
397 
398  // |||WLin 6/12/2005: the default prototype for dereference() doesn't seem right. You'd be
399  // returning a non-const reference to a member data but yet the method is const. This may
400  // work with pointers but that seems to be easier to deal with using const_cast. For
401  // objects to work it takes more. Currently no clients are making non-const calls from the
402  // return value of this method, so I made the return value const. If this changes, then
403  // we'll have to make a different change instead, either make this method non-const or the
404  // member data mutable (yuck)
405 // boost::graph_traits<XMLReferenceGraph>::edge_descriptor& dereference() const { return reinterpret_cast<boost::graph_traits<XMLReferenceGraph>::edge_descriptor>(fData); }
406  const boost::graph_traits<XMLReferenceGraph>::edge_descriptor& dereference() const { return fData; }
407 
408  void advance(int32 n)
409  {
410  ASSERT_FAIL("XMLVirtualDepthFirstTreeIterator::increment: not yet implemented");
411  }
412 
413  // member data
414  boost::graph_traits<XMLReferenceGraph>::edge_descriptor fData;
415 };
416 
417 
418 //template <class T>
419 // std::pair<T, T>
420 //virtual_out_edges(boost::graph_traits<XMLReferenceGraph>::vertex_descriptor v, const XMLReferenceGraph& g);
421 
422 //template <>
423 // std::pair<XMLVirtualDepthFirstTreeIterator, XMLVirtualDepthFirstTreeIterator>
424 //virtual_out_edges<XMLVirtualDepthFirstTreeIterator>(boost::graph_traits<XMLReferenceGraph>::vertex_descriptor v, const XMLReferenceGraph& g);
425 
426 //template <>
427 // std::pair<XMLOutEdgeIterator, XMLOutEdgeIterator>
428 //virtual_out_edges<XMLOutEdgeIterator>(boost::graph_traits<XMLReferenceGraph>::vertex_descriptor v, const XMLReferenceGraph& g);
429 
430 template <class T>
431  T
432 virtual_make_iterator(boost::graph_traits<XMLReferenceGraph>::vertex_descriptor v, const XMLReferenceGraph& g);
433 
434 template <>
436 virtual_make_iterator<XMLVirtualDepthFirstTreeIterator>(boost::graph_traits<XMLReferenceGraph>::vertex_descriptor v, const XMLReferenceGraph& g);
437 
438 template <>
439  XMLOutEdgeIterator
440 virtual_make_iterator<XMLOutEdgeIterator>(boost::graph_traits<XMLReferenceGraph>::vertex_descriptor v, const XMLReferenceGraph& g);
441 
442 
443 // To get the root property from the graph
444 inline boost::graph_traits<XMLReferenceGraph>::vertex_descriptor
445 get(boost::graph_tree_root_t, const XMLReferenceGraph& g)
446 {
447  return g.RootVertex();;
448 }
449 
450 
451 #if DEBUG
452 void TraceElementInfo(const XMLReference& v);
453 #endif
454 
455 
456 #endif //__XMLReferenceGraph__
457 
458