COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 2064:2c5f81b35269

Last change on this file since 2064:2c5f81b35269 was 2016:ecb067198349, checked in by Balazs Dezso, 14 years ago

Doc rearrangement
Section readers moved to own group

File size: 39.3 KB
Line 
1/* -*- C++ -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
19///\ingroup io_group
20///\file
21///\brief Lemon Format writer.
22
23#ifndef LEMON_LEMON_WRITER_H
24#define LEMON_LEMON_WRITER_H
25
26#include <iostream>
27#include <fstream>
28#include <string>
29#include <vector>
30#include <algorithm>
31#include <map>
32#include <memory>
33
34#include <lemon/error.h>
35#include <lemon/bits/invalid.h>
36#include <lemon/graph_utils.h>
37#include <lemon/bits/item_writer.h>
38#include <lemon/bits/utility.h>
39#include <lemon/maps.h>
40#include <lemon/xy.h>
41
42#include <lemon/concept_check.h>
43#include <lemon/concept/maps.h>
44
45
46namespace lemon {
47
48  namespace _writer_bits {
49   
50    template <typename Item>
51    class ItemLabelWriter {
52    public:
53
54      bool isLabelWriter() { return true; }
55
56      void writeLabel(std::ostream&, const Item&) {}
57     
58      template <class _ItemLabelWriter>
59      struct Constraints {
60        void constraints() {
61          bool b = writer.isLabelWriter();
62          ignore_unused_variable_warning(b);
63          writer.writeLabel(os, item);
64        }
65        _ItemLabelWriter& writer;
66        std::ostream& os;
67        const Item& item;
68      };
69
70    };
71
72    template <typename Item>
73    class ItemWriter {
74    public:
75
76      void write(std::ostream&, const Item&) {}
77     
78      template <class _ItemWriter>
79      struct Constraints {
80        void constraints() {
81          writer.write(os, item);
82        }
83        _ItemWriter& writer;
84        std::ostream& os;
85        const Item& item;
86      };
87
88    };
89
90    template <typename Map>
91    struct Ref { typedef const Map& Type; };
92
93    template <typename Graph, typename Map>
94    class ForwardComposeMap {
95    public:
96      typedef typename Graph::UEdge Key;
97      typedef typename Map::Value Value;
98
99      ForwardComposeMap(const Graph& _graph, const Map& _map)
100        : graph(_graph), map(_map) {}
101     
102      Value operator[](const Key& key) {
103        return map[graph.direct(key, false)];
104      }
105
106    private:
107      typename Ref<Map>::Type map;
108      const Graph& graph;
109    };
110
111    template <typename Graph, typename Map>
112    ForwardComposeMap<Graph, Map>
113    forwardComposeMap(const Graph& graph, const Map& map) {
114      return ForwardComposeMap<Graph, Map>(graph, map);
115    }
116
117    template <typename Graph, typename Map>
118    class BackwardComposeMap {
119    public:
120      typedef typename Graph::UEdge Key;
121      typedef typename Map::Value Value;
122
123      BackwardComposeMap(const Graph& _graph, const Map& _map)
124        : graph(_graph), map(_map) {}
125     
126      Value operator[](const Key& key) {
127        return map[graph.direct(key, false)];
128      }
129
130    private:
131      typename Ref<Map>::Type map;
132      const Graph& graph;
133    };
134
135    template <typename Graph, typename Map>
136    BackwardComposeMap<Graph, Map>
137    backwardComposeMap(const Graph& graph, const Map& map) {
138      return BackwardComposeMap<Graph, Map>(graph, map);
139    }
140
141    template <typename Graph, typename Map>
142    struct Ref<ForwardComposeMap<Graph, Map> > {
143      typedef ForwardComposeMap<Graph, Map> Type;
144    };
145
146    template <typename Graph, typename Map>
147    struct Ref<BackwardComposeMap<Graph, Map> > {
148      typedef BackwardComposeMap<Graph, Map> Type;
149    };
150
151    template <typename Map>
152    struct Ref<XMap<Map> > {
153      typedef XMap<Map> Type;
154    };
155    template <typename Map>
156    struct Ref<ConstXMap<Map> > {
157      typedef ConstXMap<Map> Type;
158    };
159
160    template <typename Map>
161    struct Ref<YMap<Map> > {
162      typedef YMap<Map> Type;
163    };
164    template <typename Map>
165    struct Ref<ConstYMap<Map> > {
166      typedef ConstYMap<Map> Type;
167    };
168
169
170    template <typename _Item>   
171    class MapWriterBase {
172    public:
173      typedef _Item Item;
174
175      virtual ~MapWriterBase() {}
176
177      virtual void write(std::ostream& os, const Item& item) const = 0;
178    };
179
180
181    template <typename _Item, typename _Map, typename _Writer>
182    class MapWriter : public MapWriterBase<_Item> {
183    public:
184      typedef _Map Map;
185      typedef _Writer Writer;
186      typedef typename Writer::Value Value;
187      typedef _Item Item;
188     
189      typename _writer_bits::Ref<Map>::Type map;
190      Writer writer;
191
192      MapWriter(const Map& _map, const Writer& _writer)
193        : map(_map), writer(_writer) {}
194
195      virtual ~MapWriter() {}
196
197      virtual void write(std::ostream& os, const Item& item) const {
198        Value value = map[item];
199        writer.write(os, value);
200      }
201
202    };
203
204
205    class ValueWriterBase {
206    public:
207      virtual ~ValueWriterBase() {}
208      virtual void write(std::ostream&) = 0;
209    };
210
211    template <typename _Value, typename _Writer>
212    class ValueWriter : public ValueWriterBase {
213    public:
214      typedef _Value Value;
215      typedef _Writer Writer;
216
217      ValueWriter(const Value& _value, const Writer& _writer)
218        : value(_value), writer(_writer) {}
219
220      virtual void write(std::ostream& os) {
221        writer.write(os, value);
222      }
223    private:
224      const Value& value;
225      Writer writer;
226    };
227   
228
229    template <typename _Item>
230    class LabelWriterBase {
231    public:
232      typedef _Item Item;
233      virtual ~LabelWriterBase() {}
234      virtual void write(std::ostream&, const Item&) const = 0;
235      virtual bool isLabelWriter() const = 0;
236    };
237
238    template <typename _Item, typename _BoxedLabelWriter>
239    class LabelWriter : public LabelWriterBase<_Item> {
240    public:
241      typedef _Item Item;
242      typedef _BoxedLabelWriter BoxedLabelWriter;
243
244      const BoxedLabelWriter& labelWriter;
245
246      LabelWriter(const BoxedLabelWriter& _labelWriter)
247        : labelWriter(_labelWriter) {}
248
249      virtual void write(std::ostream& os, const Item& item) const {
250        labelWriter.writeLabel(os, item);
251      }
252
253      virtual bool isLabelWriter() const {
254        return labelWriter.isLabelWriter();
255      }
256    };
257
258  }
259
260  /// \ingroup io_group
261  /// \brief Lemon Format writer class.
262  ///
263  /// The Lemon Format contains several sections. We do not want to
264  /// determine what sections are in a lemon file we give only a framework
265  /// to write a section oriented format.
266  ///
267  /// In the Lemon Format each section starts with a line contains a \c \@
268  /// character on the first not white space position. This line is the
269  /// header line of the section. Each next lines belong to this section
270  /// while it does not starts with \c \@ character. This line can start a
271  /// new section or if it can close the file with the \c \@end line.
272  /// The file format ignore the empty lines and it may contain comments
273  /// started with a \c # character to the end of the line.
274  ///
275  /// The framework provides an abstract LemonWriter::SectionWriter class
276  /// what defines the interface of a SectionWriter. The SectionWriter
277  /// has the \c header() member function what gives back the header of the
278  /// section. After that it will be called the \c write() member which
279  /// should write the content of the section.
280  ///
281  /// \relates GraphWriter
282  /// \relates NodeSetWriter
283  /// \relates EdgeSetWriter
284  /// \relates NodesWriter
285  /// \relates EdgesWriter
286  /// \relates AttributeWriter
287  class LemonWriter {
288  public:
289
290    /// \brief Abstract base class for writing a section.
291    ///
292    /// This class has an \c header() member function what gives back
293    /// the header line of the section. The \c write() member should
294    /// write the content of the section to the stream.
295    class SectionWriter {
296      friend class LemonWriter;
297    protected:
298      /// \brief Constructor for SectionWriter.
299      ///
300      /// Constructor for SectionWriter. It attach this writer to
301      /// the given LemonWriter.
302      SectionWriter(LemonWriter& writer) {
303        writer.attach(*this);
304      }
305     
306      virtual ~SectionWriter() {}
307
308      /// \brief The header of section.
309      ///
310      /// It gives back the header of the section.
311      virtual std::string header() = 0;
312
313      /// \brief  Writer function of the section.
314      ///
315      /// Write the content of the section.
316      virtual void write(std::ostream& os) = 0;
317    };
318
319    /// \brief Constructor for LemonWriter.
320    ///
321    /// Constructor for LemonWriter which writes to the given stream.
322    LemonWriter(std::ostream& _os)
323      : os(&_os), own_os(false) {}
324
325    /// \brief Constructor for LemonWriter.
326    ///
327    /// Constructor for LemonWriter which writes to the given file.
328    LemonWriter(const std::string& filename)
329      : os(0), own_os(true) {
330      os = new std::ofstream(filename.c_str());
331    }
332
333    /// \brief Desctructor for LemonWriter.
334    ///
335    /// Desctructor for LemonWriter.
336    ~LemonWriter() {
337      if (own_os) {
338        delete os;
339      }
340    }
341
342  private:
343    LemonWriter(const LemonWriter&);
344    void operator=(const LemonWriter&);
345
346    void attach(SectionWriter& writer) {
347      writers.push_back(&writer);
348    }
349
350  public:
351
352    /// \brief Executes the LemonWriter.
353    ///
354    /// It executes the LemonWriter.
355    void run() {
356      SectionWriters::iterator it;
357      for (it = writers.begin(); it != writers.end(); ++it) {
358        *os << (*it)->header() << std::endl;
359        (*it)->write(*os);
360      }
361      *os << "@end" << std::endl;
362    }
363
364
365  private:
366
367    std::ostream* os;
368    bool own_os;
369
370    typedef std::vector<SectionWriter*> SectionWriters;
371    SectionWriters writers;
372
373  };
374
375  /// \ingroup section_io
376  /// \brief SectionWriter for writing a graph's nodeset.
377  ///
378  /// The lemon format can store multiple graph nodesets with several maps.
379  /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but
380  /// the \c nodeset_name may be empty.
381  ///
382  /// The first line of the section contains the names of the maps separated
383  /// with white spaces. Each next lines describes a node in the nodeset, and
384  /// contains the mapped values for each map.
385  ///
386  /// If the nodeset contains an \c "label" named map then it will be regarded
387  /// as label map. This map should contain only unique values and when the
388  /// \c writeLabel() member will be called with a node it will write it's
389  /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
390  /// then the label map will be the id in the graph.
391  ///
392  /// \relates LemonWriter
393  template <typename _Graph, typename _Traits = DefaultWriterTraits>
394  class NodeSetWriter : public LemonWriter::SectionWriter {
395    typedef LemonWriter::SectionWriter Parent;
396  public:
397
398    typedef _Graph Graph;
399    typedef _Traits Traits;
400    typedef typename Graph::Node Node;
401
402    /// \brief Constructor.
403    ///
404    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
405    /// attach it into the given LemonWriter. If the \c _forceLabelMap
406    /// parameter is true then the writer will write own label map when
407    /// the user does not give "label" named map.
408    NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
409                  const std::string& _name = std::string(),
410                  bool _forceLabelMap = true)
411      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
412        graph(_graph), name(_name) {}
413
414    /// \brief Destructor.
415    ///
416    /// Destructor for NodeSetWriter.
417    virtual ~NodeSetWriter() {
418      typename MapWriters::iterator it;
419      for (it = writers.begin(); it != writers.end(); ++it) {
420        delete it->second;
421      }
422    }
423
424  private:
425    NodeSetWriter(const NodeSetWriter&);
426    void operator=(const NodeSetWriter&);
427 
428  public:
429
430    /// \brief Add a new node map writer command for the writer.
431    ///
432    /// Add a new node map writer command for the writer.
433    template <typename Map>
434    NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
435      return writeNodeMap<typename Traits::
436        template Writer<typename Map::Value>, Map>(name, map);
437    }
438
439    /// \brief Add a new node map writer command for the writer.
440    ///
441    /// Add a new node map writer command for the writer.
442    template <typename Writer, typename Map>
443    NodeSetWriter& writeNodeMap(std::string name, const Map& map,
444                            const Writer& writer = Writer()) {
445      checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
446      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
447      writers.push_back(
448        make_pair(name, new _writer_bits::
449                  MapWriter<Node, Map, Writer>(map, writer)));
450      return *this;
451    }
452
453  protected:
454
455    /// \brief The header of the section.
456    ///
457    /// It gives back the header of the section.
458    virtual std::string header() {
459      return "@nodeset " + name;
460    }
461
462    /// \brief  Writer function of the section.
463    ///
464    /// Write the content of the section.
465    virtual void write(std::ostream& os) {
466      for (int i = 0; i < (int)writers.size(); ++i) {
467        if (writers[i].first == "label" || (writers[i].first == "id" && labelMap == 0)) {
468          labelMap = writers[i].second;
469          forceLabelMap = false;
470          break;
471        }
472      }
473      if (forceLabelMap) {
474        os << "label\t";
475      }
476      for (int i = 0; i < (int)writers.size(); ++i) {
477        os << writers[i].first << '\t';
478      }
479      os << std::endl;
480      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
481        if (forceLabelMap) {
482          os << graph.id(it) << '\t';
483        }
484        for (int i = 0; i < (int)writers.size(); ++i) {
485          writers[i].second->write(os, it);
486          os << '\t';
487        }
488        os << std::endl;
489      }
490    }
491
492  public:
493
494    /// \brief Returns true if the nodeset can write the labels of the nodes.
495    ///
496    /// Returns true if the nodeset can write the labels of the nodes.
497    /// It is possible only if an "label" named map was written or the
498    /// \c _forceLabelMap constructor parameter was true.
499    bool isLabelWriter() const {
500      return labelMap != 0 || forceLabelMap;
501    }
502
503    /// \brief Write the label of the given node.
504    ///
505    /// It writes the label of the given node. If there was written an "label"
506    /// named map then it will write the map value belongs to the node.
507    /// Otherwise if the \c forceLabel parameter was true it will write
508    /// its label in the graph.
509    void writeLabel(std::ostream& os, const Node& item) const {
510      if (forceLabelMap) {
511        os << graph.id(item);
512      } else {
513        labelMap->write(os, item);
514      }
515    }
516
517  private:
518
519    typedef std::vector<std::pair<std::string, _writer_bits::
520                                  MapWriterBase<Node>*> > MapWriters;
521    MapWriters writers;
522
523    _writer_bits::MapWriterBase<Node>* labelMap;
524    bool forceLabelMap;
525   
526    const Graph& graph;   
527    std::string name;
528
529  };
530
531  /// \ingroup section_io
532  /// \brief SectionWriter for writing a graph's edgesets.
533  ///
534  /// The lemon format can store multiple graph edgesets with several maps.
535  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but
536  /// the \c edgeset_name may be empty.
537  ///
538  /// The first line of the section contains the names of the maps separated
539  /// with white spaces. Each next lines describes a edge in the edgeset. The
540  /// line contains the source and the target nodes' label and the mapped
541  /// values for each map.
542  ///
543  /// If the edgeset contains an \c "label" named map then it will be regarded
544  /// as label map. This map should contain only unique values and when the
545  /// \c writeLabel() member will be called with an edge it will write it's
546  /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
547  /// then the label map will be the id in the graph.
548  ///
549  /// The edgeset writer needs a node label writer to identify which nodes
550  /// have to be connected. If a NodeSetWriter can write the nodes' label,
551  /// it will be able to use with this class.
552  ///
553  /// \relates LemonWriter
554  template <typename _Graph, typename _Traits = DefaultWriterTraits>
555  class EdgeSetWriter : public LemonWriter::SectionWriter {
556    typedef LemonWriter::SectionWriter Parent;
557  public:
558
559    typedef _Graph Graph;
560    typedef _Traits Traits;
561    typedef typename Graph::Node Node;
562    typedef typename Graph::Edge Edge;
563
564    /// \brief Constructor.
565    ///
566    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
567    /// attach it into the given LemonWriter. It will write node labels by
568    /// the \c _nodeLabelWriter. If the \c _forceLabelMap parameter is true
569    /// then the writer will write own label map if the user does not give
570    /// "label" named map.
571    template <typename NodeLabelWriter>
572    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
573                  const NodeLabelWriter& _nodeLabelWriter,
574                  const std::string& _name = std::string(),
575                  bool _forceLabelMap = true)
576      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
577        graph(_graph), name(_name) {
578      checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
579      nodeLabelWriter.reset(new _writer_bits::
580                         LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
581    }
582
583    /// \brief Destructor.
584    ///
585    /// Destructor for EdgeSetWriter.
586    virtual ~EdgeSetWriter() {
587      typename MapWriters::iterator it;
588      for (it = writers.begin(); it != writers.end(); ++it) {
589        delete it->second;
590      }
591    }
592
593  private:
594    EdgeSetWriter(const EdgeSetWriter&);
595    void operator=(const EdgeSetWriter&);
596
597  public:
598
599    /// \brief Add a new edge map writer command for the writer.
600    ///
601    /// Add a new edge map writer command for the writer.
602    template <typename Map>
603    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
604      return writeEdgeMap<typename Traits::
605        template Writer<typename Map::Value>, Map>(name, map);
606    }
607
608    /// \brief Add a new edge map writer command for the writer.
609    ///
610    /// Add a new edge map writer command for the writer.
611    template <typename Writer, typename Map>
612    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
613                            const Writer& writer = Writer()) {
614      checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
615      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
616      writers.push_back(
617        make_pair(name, new _writer_bits::
618                  MapWriter<Edge, Map, Writer>(map, writer)));
619      return *this;
620    }
621
622  protected:
623
624    /// \brief The header of the section.
625    ///
626    /// It gives back the header of the section.
627    virtual std::string header() {
628      return "@edgeset " + name;
629    }
630
631    /// \brief  Writer function of the section.
632    ///
633    /// Write the content of the section.
634    virtual void write(std::ostream& os) {
635      if (!nodeLabelWriter->isLabelWriter()) {
636        throw DataFormatError("Cannot find nodeset or label map");
637      }
638      for (int i = 0; i < (int)writers.size(); ++i) {
639        if (writers[i].first == "label" || (writers[i].first == "id" && labelMap == 0)) {
640          labelMap = writers[i].second;
641          forceLabelMap = false;
642          break;
643        }
644      }
645      os << "\t\t";
646      if (forceLabelMap) {
647        os << "label\t";
648      }
649      for (int i = 0; i < (int)writers.size(); ++i) {
650        os << writers[i].first << '\t';
651      }
652      os << std::endl;
653      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
654        nodeLabelWriter->write(os, graph.source(it));
655        os << '\t';
656        nodeLabelWriter->write(os, graph.target(it));
657        os << '\t';
658        if (forceLabelMap) {
659          os << graph.id(it) << '\t';
660        }
661        for (int i = 0; i < (int)writers.size(); ++i) {
662          writers[i].second->write(os, it);
663          os << '\t';
664        }
665        os << std::endl;
666      }
667    }
668
669  public:
670
671    /// \brief Returns true if the edgeset can write the labels of the edges.
672    ///
673    /// Returns true if the edgeset can write the labels of the edges.
674    /// It is possible only if an "label" named map was written or the
675    /// \c _forceLabelMap constructor parameter was true.
676    bool isLabelWriter() const {
677      return forceLabelMap || labelMap != 0;
678    }
679
680    /// \brief Write the label of the given edge.
681    ///
682    /// It writes the label of the given edge. If there was written an "label"
683    /// named map then it will write the map value belongs to the edge.
684    /// Otherwise if the \c forceLabel parameter was true it will write
685    /// its label in the graph.
686    void writeLabel(std::ostream& os, const Edge& item) const {
687      if (forceLabelMap) {
688        os << graph.id(item);
689      } else {
690        labelMap->write(os, item);
691      }
692    }
693
694  private:
695
696    typedef std::vector<std::pair<std::string, _writer_bits::
697                                  MapWriterBase<Edge>*> > MapWriters;
698    MapWriters writers;
699
700    _writer_bits::MapWriterBase<Edge>* labelMap;
701    bool forceLabelMap;
702   
703    const Graph& graph;   
704    std::string name;
705
706    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
707  };
708
709  /// \ingroup section_io
710  /// \brief SectionWriter for writing a undirected edgeset.
711  ///
712  /// The lemon format can store multiple undirected edgesets with several
713  /// maps. The undirected edgeset section's header line is \c \@uedgeset
714  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
715  ///
716  /// The first line of the section contains the names of the maps separated
717  /// with white spaces. Each next lines describes an undirected edge in the
718  /// edgeset. The line contains the two connected nodes' label and the mapped
719  /// values for each undirected map.
720  ///
721  /// The section can handle the directed as a syntactical sugar. Two
722  /// undirected edge map describes one directed edge map. This two maps
723  /// are the forward map and the backward map and the names of this map
724  /// is near the same just with a prefix \c '+' or \c '-' character
725  /// difference.
726  ///
727  /// If the edgeset contains an \c "label" named map then it will be regarded
728  /// as label map. This map should contain only unique values and when the
729  /// \c writeLabel() member will be called with an undirected edge it will
730  /// write it's label. Otherwise if the \c _forceLabelMap constructor
731  /// parameter is true then the label map will be the id in the graph.
732  ///
733  /// The undirected edgeset writer needs a node label writer to identify
734  /// which nodes have to be connected. If a NodeSetWriter can write the
735  /// nodes' label, it will be able to use with this class.
736  ///
737  /// \relates LemonWriter
738  template <typename _Graph, typename _Traits = DefaultWriterTraits>
739  class UEdgeSetWriter : public LemonWriter::SectionWriter {
740    typedef LemonWriter::SectionWriter Parent;
741  public:
742
743    typedef _Graph Graph;
744    typedef _Traits Traits;
745    typedef typename Graph::Node Node;
746    typedef typename Graph::Edge Edge;
747    typedef typename Graph::UEdge UEdge;
748
749    /// \brief Constructor.
750    ///
751    /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
752    /// and attach it into the given LemonWriter. It will write node labels by
753    /// the \c _nodeLabelWriter. If the \c _forceLabelMap parameter is true
754    /// then the writer will write own label map if the user does not give
755    /// "label" named map.
756    template <typename NodeLabelWriter>
757    UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
758                       const NodeLabelWriter& _nodeLabelWriter,
759                       const std::string& _name = std::string(),
760                       bool _forceLabelMap = true)
761      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
762        graph(_graph), name(_name) {
763      checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
764      nodeLabelWriter.reset(new _writer_bits::
765                         LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
766    }
767
768    /// \brief Destructor.
769    ///
770    /// Destructor for UEdgeSetWriter.
771    virtual ~UEdgeSetWriter() {
772      typename MapWriters::iterator it;
773      for (it = writers.begin(); it != writers.end(); ++it) {
774        delete it->second;
775      }
776    }
777
778  private:
779    UEdgeSetWriter(const UEdgeSetWriter&);
780    void operator=(const UEdgeSetWriter&);
781
782  public:
783
784    /// \brief Add a new undirected edge map writer command for the writer.
785    ///
786    /// Add a new undirected map writer command for the writer.
787    template <typename Map>
788    UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map) {
789      return writeUEdgeMap<typename Traits::
790        template Writer<typename Map::Value>, Map>(name, map);
791    }
792
793    /// \brief Add a new undirected map writer command for the writer.
794    ///
795    /// Add a new undirected map writer command for the writer.
796    template <typename Writer, typename Map>
797    UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map,
798                                          const Writer& writer = Writer()) {
799      checkConcept<concept::ReadMap<UEdge, typename Map::Value>, Map>();
800      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
801      writers.push_back(
802        make_pair(name, new _writer_bits::
803                  MapWriter<UEdge, Map, Writer>(map, writer)));
804      return *this;
805    }
806
807    /// \brief Add a new directed edge map writer command for the writer.
808    ///
809    /// Add a new directed map writer command for the writer.
810    template <typename Map>
811    UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
812      return writeEdgeMap<typename Traits::
813        template Writer<typename Map::Value>, Map>(name, map);
814    }
815
816    /// \brief Add a new directed map writer command for the writer.
817    ///
818    /// Add a new directed map writer command for the writer.
819    template <typename Writer, typename Map>
820    UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
821                                     const Writer& writer = Writer()) {
822      checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
823      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
824      writeUEdge("+" + name,
825                     _writer_bits::forwardComposeMap(graph, map), writer);
826      writeUEdge("-" + name,
827                     _writer_bits::backwardComposeMap(graph, map), writer);
828      return *this;
829    }
830
831  protected:
832
833    /// \brief The header of the section.
834    ///
835    /// It gives back the header of the section.
836    virtual std::string header() {
837      return "@uedgeset " + name;
838    }
839
840    /// \brief  Writer function of the section.
841    ///
842    /// Write the content of the section.
843    virtual void write(std::ostream& os) {
844      if (!nodeLabelWriter->isLabelWriter()) {
845        throw DataFormatError("Cannot find nodeset or label map");
846      }
847      for (int i = 0; i < (int)writers.size(); ++i) {
848        if (writers[i].first == "label") {
849          labelMap = writers[i].second;
850          forceLabelMap = false;
851          break;
852        }
853      }
854      os << "\t\t";
855      if (forceLabelMap) {
856        os << "label\t";
857      }
858      for (int i = 0; i < (int)writers.size(); ++i) {
859        os << writers[i].first << '\t';
860      }
861      os << std::endl;
862      for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
863        nodeLabelWriter->write(os, graph.source(it));
864        os << '\t';
865        nodeLabelWriter->write(os, graph.target(it));
866        os << '\t';
867        if (forceLabelMap) {
868          os << graph.id(it) << '\t';
869        }
870        for (int i = 0; i < (int)writers.size(); ++i) {
871          writers[i].second->write(os, it);
872          os << '\t';
873        }
874        os << std::endl;
875      }
876    }
877
878  public:
879
880    /// \brief Returns true if the undirected edgeset can write the labels of
881    /// the edges.
882    ///
883    /// Returns true if the undirected edgeset can write the labels of the
884    /// undirected edges. It is possible only if an "label" named map was
885    /// written or the \c _forceLabelMap constructor parameter was true.
886    bool isLabelWriter() const {
887      return forceLabelMap || labelMap != 0;
888    }
889
890    /// \brief Write the label of the given undirected edge.
891    ///
892    /// It writes the label of the given undirected edge. If there was written
893    /// an "label" named map then it will write the map value belongs to the
894    /// undirected edge. Otherwise if the \c forceLabel parameter was true it
895    /// will write its id in the graph.
896    void writeLabel(std::ostream& os, const UEdge& item) const {
897      if (forceLabelMap) {
898        os << graph.id(item);
899      } else {
900        labelMap->write(os, item);
901      }
902    }
903
904    /// \brief Write the label of the given edge.
905    ///
906    /// It writes the label of the given edge. If there was written
907    /// an "label" named map then it will write the map value belongs to the
908    /// edge. Otherwise if the \c forceLabel parameter was true it
909    /// will write its id in the graph. If the edge is forward map
910    /// then its prefix character is \c '+' elsewhere \c '-'.
911    void writeLabel(std::ostream& os, const Edge& item) const {
912      if (graph.direction(item)) {
913        os << "+ ";
914      } else {
915        os << "- ";
916      }
917      if (forceLabelMap) {
918        os << graph.id(item);
919      } else {
920        labelMap->write(os, item);
921      }
922    }
923
924  private:
925
926    typedef std::vector<std::pair<std::string, _writer_bits::
927                                  MapWriterBase<UEdge>*> > MapWriters;
928    MapWriters writers;
929
930    _writer_bits::MapWriterBase<UEdge>* labelMap;
931    bool forceLabelMap;
932   
933    const Graph& graph;   
934    std::string name;
935
936    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
937  };
938
939  /// \ingroup section_io
940  /// \brief SectionWriter for writing named nodes.
941  ///
942  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
943  /// \c nodes_name may be empty.
944  ///
945  /// Each line in the section contains the name of the node and
946  /// then the node label.
947  ///
948  /// \relates LemonWriter
949  template <typename _Graph>
950  class NodeWriter : public LemonWriter::SectionWriter {
951    typedef LemonWriter::SectionWriter Parent;
952    typedef _Graph Graph;
953    typedef typename Graph::Node Node;
954  public:
955   
956    /// \brief Constructor.
957    ///
958    /// Constructor for NodeWriter. It creates the NodeWriter and
959    /// attach it into the given LemonWriter. The given \c _LabelWriter
960    /// will write the nodes' label what can be a nodeset writer.
961    template <typename _LabelWriter>
962    NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
963               const std::string& _name = std::string())
964      : Parent(_writer), name(_name) {
965      checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
966      labelWriter.reset(new _writer_bits::LabelWriter<Node, _LabelWriter>
967                        (_labelWriter));
968    }
969
970
971    /// \brief Destructor.
972    ///
973    /// Destructor for NodeWriter.
974    virtual ~NodeWriter() {}
975
976  private:
977    NodeWriter(const NodeWriter&);
978    void operator=(const NodeWriter&);
979
980  public:
981
982    /// \brief Add a node writer command for the NodeWriter.
983    ///
984    /// Add a node writer command for the NodeWriter.
985    void writeNode(const std::string& name, const Node& item) {
986      writers.push_back(make_pair(name, &item));
987    }
988
989  protected:
990
991    /// \brief The header of the section.
992    ///
993    /// It gives back the header of the section.
994    virtual std::string header() {
995      return "@nodes " + name;
996    }
997
998    /// \brief  Writer function of the section.
999    ///
1000    /// Write the content of the section.
1001    virtual void write(std::ostream& os) {
1002      if (!labelWriter->isLabelWriter()) {
1003        throw DataFormatError("Cannot find nodeset or label map");
1004      }
1005      for (int i = 0; i < (int)writers.size(); ++i) {
1006        os << writers[i].first << ' ';
1007        labelWriter->write(os, *(writers[i].second));
1008        os << std::endl;
1009      }
1010    }
1011   
1012  private:
1013
1014    std::string name;
1015
1016    typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
1017    NodeWriters writers;
1018    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
1019  };
1020
1021  /// \ingroup section_io
1022  /// \brief SectionWriter for writing named edges.
1023  ///
1024  /// The edges section's header line is \c \@edges \c edges_name, but the
1025  /// \c edges_name may be empty.
1026  ///
1027  /// Each line in the section contains the name of the edge and
1028  /// then the edge label.
1029  ///
1030  /// \relates LemonWriter
1031  template <typename _Graph>
1032  class EdgeWriter : public LemonWriter::SectionWriter {
1033    typedef LemonWriter::SectionWriter Parent;
1034    typedef _Graph Graph;
1035    typedef typename Graph::Edge Edge;
1036  public:
1037   
1038    /// \brief Constructor.
1039    ///
1040    /// Constructor for EdgeWriter. It creates the EdgeWriter and
1041    /// attach it into the given LemonWriter. The given \c _LabelWriter
1042    /// will write the edges' label what can be a edgeset writer.
1043    template <typename _LabelWriter>
1044    EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
1045               const std::string& _name = std::string())
1046      : Parent(_writer), name(_name) {
1047      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
1048      labelWriter.reset(new _writer_bits::LabelWriter<Edge, _LabelWriter>(_labelWriter));
1049    }
1050
1051    /// \brief Destructor.
1052    ///
1053    /// Destructor for EdgeWriter.
1054    virtual ~EdgeWriter() {}
1055  private:
1056    EdgeWriter(const EdgeWriter&);
1057    void operator=(const EdgeWriter&);
1058
1059  public:
1060
1061    /// \brief Add an edge writer command for the EdgeWriter.
1062    ///
1063    /// Add an edge writer command for the EdgeWriter.
1064    void writeEdge(const std::string& name, const Edge& item) {
1065      writers.push_back(make_pair(name, &item));
1066    }
1067
1068  protected:
1069
1070    /// \brief The header of the section.
1071    ///
1072    /// It gives back the header of the section.
1073    virtual std::string header() {
1074      return "@edges " + name;
1075    }
1076
1077    /// \brief  Writer function of the section.
1078    ///
1079    /// Write the content of the section.
1080    virtual void write(std::ostream& os) {
1081      if (!labelWriter->isLabelWriter()) {
1082        throw DataFormatError("Cannot find edgeset or label map");
1083      }
1084      for (int i = 0; i < (int)writers.size(); ++i) {
1085        os << writers[i].first << ' ';
1086        labelWriter->write(os, *(writers[i].second));
1087        os << std::endl;
1088      }
1089    }
1090   
1091  private:
1092
1093    std::string name;
1094
1095    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1096    EdgeWriters writers;
1097
1098    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
1099  };
1100
1101  /// \ingroup section_io
1102  /// \brief SectionWriter for writing named undirected edges.
1103  ///
1104  /// The undirected edges section's header line is \c \@uedges
1105  /// \c uedges_name, but the \c uedges_name may be empty.
1106  ///
1107  /// Each line in the section contains the name of the undirected edge and
1108  /// then the undirected edge label.
1109  ///
1110  /// \relates LemonWriter
1111  template <typename _Graph>
1112  class UEdgeWriter : public LemonWriter::SectionWriter {
1113    typedef LemonWriter::SectionWriter Parent;
1114    typedef _Graph Graph;
1115    typedef typename Graph::Node Node;
1116    typedef typename Graph::Edge Edge;
1117    typedef typename Graph::UEdge UEdge;
1118  public:
1119   
1120    /// \brief Constructor.
1121    ///
1122    /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
1123    /// attach it into the given LemonWriter. The given \c _LabelWriter
1124    /// will write the undirected edges' label what can be an undirected
1125    /// edgeset writer.
1126    template <typename _LabelWriter>
1127    UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
1128               const std::string& _name = std::string())
1129      : Parent(_writer), name(_name) {
1130      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
1131      checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
1132      uEdgeLabelWriter.reset(new _writer_bits::
1133                              LabelWriter<UEdge, _LabelWriter>(_labelWriter));
1134      edgeLabelWriter.reset(new _writer_bits::
1135                         LabelWriter<Edge, _LabelWriter>(_labelWriter));
1136    }
1137
1138    /// \brief Destructor.
1139    ///
1140    /// Destructor for UEdgeWriter.
1141    virtual ~UEdgeWriter() {}
1142  private:
1143    UEdgeWriter(const UEdgeWriter&);
1144    void operator=(const UEdgeWriter&);
1145
1146  public:
1147
1148    /// \brief Add an edge writer command for the UEdgeWriter.
1149    ///
1150    /// Add an edge writer command for the UEdgeWriter.
1151    void writeEdge(const std::string& name, const Edge& item) {
1152      edgeWriters.push_back(make_pair(name, &item));
1153    }
1154
1155    /// \brief Add an undirected edge writer command for the UEdgeWriter.
1156    ///
1157    /// Add an undirected edge writer command for the UEdgeWriter.
1158    void writeUEdge(const std::string& name, const UEdge& item) {
1159      uEdgeWriters.push_back(make_pair(name, &item));
1160    }
1161
1162  protected:
1163
1164    /// \brief The header of the section.
1165    ///
1166    /// It gives back the header of the section.
1167    virtual std::string header() {
1168      return "@uedges " + name;
1169    }
1170
1171    /// \brief  Writer function of the section.
1172    ///
1173    /// Write the content of the section.
1174    virtual void write(std::ostream& os) {
1175      if (!edgeLabelWriter->isLabelWriter()) {
1176        throw DataFormatError("Cannot find undirected edgeset or label map");
1177      }
1178      if (!uEdgeLabelWriter->isLabelWriter()) {
1179        throw DataFormatError("Cannot find undirected edgeset or label map");
1180      }
1181      for (int i = 0; i < (int)uEdgeWriters.size(); ++i) {
1182        os << uEdgeWriters[i].first << ' ';
1183        uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
1184        os << std::endl;
1185      }
1186      for (int i = 0; i < (int)edgeWriters.size(); ++i) {
1187        os << edgeWriters[i].first << ' ';
1188        edgeLabelWriter->write(os, *(edgeWriters[i].second));
1189        os << std::endl;
1190      }
1191    }
1192   
1193  private:
1194
1195    std::string name;
1196
1197    typedef std::vector<std::pair<std::string,
1198                                  const UEdge*> > UEdgeWriters;
1199    UEdgeWriters uEdgeWriters;
1200    std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
1201
1202    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1203    EdgeWriters edgeWriters;
1204    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
1205
1206  };
1207
1208  /// \ingroup section_io
1209  /// \brief SectionWriter for attributes.
1210  ///
1211  /// The lemon format can store multiple attribute set. Each set has
1212  /// the header line \c \@attributes \c attributes_name, but the
1213  /// attributeset_name may be empty.
1214  ///
1215  /// The attributeset section contains several lines. Each of them starts
1216  /// with the name of attribute and then the value.
1217  ///
1218  /// \relates LemonWriter
1219  template <typename _Traits = DefaultWriterTraits>
1220  class AttributeWriter : public LemonWriter::SectionWriter {
1221    typedef LemonWriter::SectionWriter Parent;
1222    typedef _Traits Traits;
1223  public:
1224    /// \brief Constructor.
1225    ///
1226    /// Constructor for AttributeWriter. It creates the AttributeWriter and
1227    /// attach it into the given LemonWriter.
1228    AttributeWriter(LemonWriter& _writer,
1229                    const std::string& _name = std::string())
1230      : Parent(_writer), name(_name) {}
1231
1232    /// \brief Destructor.
1233    ///
1234    /// Destructor for AttributeWriter.
1235    virtual ~AttributeWriter() {
1236      typename Writers::iterator it;
1237      for (it = writers.begin(); it != writers.end(); ++it) {
1238        delete it->second;
1239      }
1240    }
1241
1242  private:
1243    AttributeWriter(const AttributeWriter&);
1244    void operator=(AttributeWriter&);
1245
1246  public:
1247    /// \brief Add an attribute writer command for the writer.
1248    ///
1249    /// Add an attribute writer command for the writer.
1250    template <typename Value>
1251    AttributeWriter& writeAttribute(const std::string& name,
1252                                    const Value& value) {
1253      return
1254        writeAttribute<typename Traits::template Writer<Value> >(name, value);
1255    }
1256
1257    /// \brief Add an attribute writer command for the writer.
1258    ///
1259    /// Add an attribute writer command for the writer.
1260    template <typename Writer, typename Value>
1261    AttributeWriter& writeAttribute(const std::string& name,
1262                                    const Value& value,
1263                                    const Writer& writer = Writer()) {
1264      checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
1265      writers.push_back(make_pair(name, new _writer_bits::
1266                                  ValueWriter<Value, Writer>(value, writer)));
1267      return *this;
1268    }
1269
1270  protected:
1271
1272    /// \brief The header of section.
1273    ///
1274    /// It gives back the header of the section.
1275    std::string header() {
1276      return "@attributes " + name;
1277    }
1278
1279    /// \brief  Writer function of the section.
1280    ///
1281    /// Write the content of the section.
1282    void write(std::ostream& os) {
1283      typename Writers::iterator it;
1284      for (it = writers.begin(); it != writers.end(); ++it) {
1285        os << it->first << ' ';
1286        it->second->write(os);
1287        os << std::endl;
1288      }
1289    }   
1290
1291  private:
1292    std::string name;
1293
1294    typedef std::vector<std::pair<std::string,
1295                                  _writer_bits::ValueWriterBase*> > Writers;
1296    Writers writers; 
1297  };
1298
1299
1300}
1301#endif
Note: See TracBrowser for help on using the repository browser.