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