src/lemon/lemon_writer.h
changeset 1435 8e85e6bbefdf
parent 1421 7a21e1414c38
equal deleted inserted replaced
3:eff9af67fc3f -1:000000000000
     1 /* -*- C++ -*-
       
     2  * src/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