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