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