lemon/lemon_writer.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1690 7db44a7ab939
child 1845 f8bbfed86036
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
     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