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