lemon/lemon_writer.h
author alpar
Thu, 02 Feb 2006 08:51:10 +0000
changeset 1940 e47d0614a489
parent 1901 723b2b81d900
child 1956 a055123339d5
permissions -rw-r--r--
- also works off-line
- icc-8.0 in (not) tested, as well.
     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 ItemLabelWriter {
    50     public:
    51 
    52       bool isLabelWriter() { return true; }
    53 
    54       void writeLabel(std::ostream&, const Item&) {}
    55       
    56       template <class _ItemLabelWriter>
    57       struct Constraints {
    58 	void constraints() {
    59 	  bool b = writer.isLabelWriter();
    60 	  ignore_unused_variable_warning(b);
    61 	  writer.writeLabel(os, item);
    62 	}
    63 	_ItemLabelWriter& 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::UEdge 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::UEdge 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 LabelWriterBase {
   229     public:
   230       typedef _Item Item;
   231       virtual ~LabelWriterBase() {}
   232       virtual void write(std::ostream&, const Item&) const = 0;
   233       virtual bool isLabelWriter() const = 0;
   234     };
   235 
   236     template <typename _Item, typename _BoxedLabelWriter>
   237     class LabelWriter : public LabelWriterBase<_Item> {
   238     public:
   239       typedef _Item Item;
   240       typedef _BoxedLabelWriter BoxedLabelWriter;
   241 
   242       const BoxedLabelWriter& labelWriter;
   243 
   244       LabelWriter(const BoxedLabelWriter& _labelWriter) 
   245 	: labelWriter(_labelWriter) {}
   246 
   247       virtual void write(std::ostream& os, const Item& item) const {
   248 	labelWriter.writeLabel(os, item);
   249       }
   250 
   251       virtual bool isLabelWriter() const {
   252 	return labelWriter.isLabelWriter();
   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_name, but 
   378   /// the \c nodeset_name 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 "label" named map then it will be regarded
   385   /// as label map. This map should contain only unique values and when the 
   386   /// \c writeLabel() member will be called with a node it will write it's 
   387   /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
   388   /// then the label 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 _forceLabelMap
   404     /// parameter is true then the writer will write own label map when
   405     /// the user does not give "label" named map.
   406     NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   407 		  const std::string& _name = std::string(), 
   408 		  bool _forceLabelMap = true) 
   409       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), 
   410 	graph(_graph), name(_name) {}
   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 " + name;
   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 == "label" || (writers[i].first == "id" && labelMap == 0)) {
   466 	  labelMap = writers[i].second;
   467 	  forceLabelMap = false;
   468 	  break;
   469 	}
   470       }
   471       if (forceLabelMap) {
   472 	os << "label\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 (forceLabelMap) {
   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 labels of the nodes.
   493     ///
   494     /// Returns true if the nodeset can write the labels of the nodes.
   495     /// It is possible only if an "label" named map was written or the 
   496     /// \c _forceLabelMap constructor parameter was true.
   497     bool isLabelWriter() const {
   498       return labelMap != 0 || forceLabelMap;
   499     }
   500 
   501     /// \brief Write the label of the given node.
   502     ///
   503     /// It writes the label of the given node. If there was written an "label"
   504     /// named map then it will write the map value belongs to the node.
   505     /// Otherwise if the \c forceLabel parameter was true it will write
   506     /// its label in the graph. 
   507     void writeLabel(std::ostream& os, const Node& item) const {
   508       if (forceLabelMap) {
   509 	os << graph.id(item);
   510       } else {
   511 	labelMap->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>* labelMap;
   522     bool forceLabelMap;
   523    
   524     const Graph& graph;   
   525     std::string name;
   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_name, but 
   534   /// the \c edgeset_name 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' label and the mapped 
   539   /// values for each map.
   540   ///
   541   /// If the edgeset contains an \c "label" named map then it will be regarded
   542   /// as label map. This map should contain only unique values and when the 
   543   /// \c writeLabel() member will be called with an edge it will write it's 
   544   /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
   545   /// then the label map will be the id in the graph.
   546   ///
   547   /// The edgeset writer needs a node label writer to identify which nodes
   548   /// have to be connected. If a NodeSetWriter can write the nodes' label,
   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 labels by
   566     /// the \c _nodeLabelWriter. If the \c _forceLabelMap parameter is true 
   567     /// then the writer will write own label map if the user does not give 
   568     /// "label" named map.
   569     template <typename NodeLabelWriter>
   570     EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   571 		  const NodeLabelWriter& _nodeLabelWriter, 
   572 		  const std::string& _name = std::string(),
   573 		  bool _forceLabelMap = true)
   574       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
   575 	graph(_graph), name(_name) {
   576       checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
   577       nodeLabelWriter.reset(new _writer_bits::
   578 			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
   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 " + name;
   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 (!nodeLabelWriter->isLabelWriter()) {
   634 	throw DataFormatError("Cannot find nodeset or label map");
   635       }
   636       for (int i = 0; i < (int)writers.size(); ++i) {
   637 	if (writers[i].first == "label" || (writers[i].first == "id" && labelMap == 0)) {
   638 	  labelMap = writers[i].second;
   639 	  forceLabelMap = false;
   640 	  break;
   641 	}
   642       }
   643       os << "\t\t";
   644       if (forceLabelMap) {
   645 	os << "label\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 	nodeLabelWriter->write(os, graph.source(it));
   653 	os << '\t';
   654 	nodeLabelWriter->write(os, graph.target(it));
   655 	os << '\t';
   656 	if (forceLabelMap) {
   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 labels of the edges.
   670     ///
   671     /// Returns true if the edgeset can write the labels of the edges.
   672     /// It is possible only if an "label" named map was written or the 
   673     /// \c _forceLabelMap constructor parameter was true.
   674     bool isLabelWriter() const {
   675       return forceLabelMap || labelMap != 0;
   676     }
   677 
   678     /// \brief Write the label of the given edge.
   679     ///
   680     /// It writes the label of the given edge. If there was written an "label"
   681     /// named map then it will write the map value belongs to the edge.
   682     /// Otherwise if the \c forceLabel parameter was true it will write
   683     /// its label in the graph. 
   684     void writeLabel(std::ostream& os, const Edge& item) const {
   685       if (forceLabelMap) {
   686 	os << graph.id(item);
   687       } else {
   688 	labelMap->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>* labelMap;
   699     bool forceLabelMap;
   700    
   701     const Graph& graph;   
   702     std::string name;
   703 
   704     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
   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 \@uedgeset 
   712   /// \c uedgeset_name, but the \c uedgeset_name 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' label 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 "label" named map then it will be regarded
   726   /// as label map. This map should contain only unique values and when the 
   727   /// \c writeLabel() member will be called with an undirected edge it will 
   728   /// write it's label. Otherwise if the \c _forceLabelMap constructor 
   729   /// parameter is true then the label map will be the id in the graph.
   730   ///
   731   /// The undirected edgeset writer needs a node label writer to identify 
   732   /// which nodes have to be connected. If a NodeSetWriter can write the 
   733   /// nodes' label, it will be able to use with this class.
   734   ///
   735   /// \relates LemonWriter
   736   template <typename _Graph, typename _Traits = DefaultWriterTraits>
   737   class UEdgeSetWriter : 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::UEdge UEdge;
   746 
   747     /// \brief Constructor.
   748     ///
   749     /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
   750     /// and attach it into the given LemonWriter. It will write node labels by
   751     /// the \c _nodeLabelWriter. If the \c _forceLabelMap parameter is true 
   752     /// then the writer will write own label map if the user does not give 
   753     /// "label" named map.
   754     template <typename NodeLabelWriter>
   755     UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   756 		       const NodeLabelWriter& _nodeLabelWriter, 
   757 		       const std::string& _name = std::string(),
   758 		       bool _forceLabelMap = true)
   759       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
   760 	graph(_graph), name(_name) {
   761       checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
   762       nodeLabelWriter.reset(new _writer_bits::
   763 			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
   764     } 
   765 
   766     /// \brief Destructor.
   767     ///
   768     /// Destructor for UEdgeSetWriter.
   769     virtual ~UEdgeSetWriter() {
   770       typename MapWriters::iterator it;
   771       for (it = writers.begin(); it != writers.end(); ++it) {
   772 	delete it->second;
   773       }
   774     }
   775 
   776   private:
   777     UEdgeSetWriter(const UEdgeSetWriter&);
   778     void operator=(const UEdgeSetWriter&);
   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     UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map) {
   787       return writeUEdgeMap<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     UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map, 
   796 					  const Writer& writer = Writer()) {
   797       checkConcept<concept::ReadMap<UEdge, 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<UEdge, 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     UEdgeSetWriter& 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     UEdgeSetWriter& 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       writeUEdge("+" + name, 
   823 		     _writer_bits::forwardComposeMap(graph, map), writer);
   824       writeUEdge("-" + 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 "@uedgeset " + name;
   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 (!nodeLabelWriter->isLabelWriter()) {
   843 	throw DataFormatError("Cannot find nodeset or label map");
   844       }
   845       for (int i = 0; i < (int)writers.size(); ++i) {
   846 	if (writers[i].first == "label") {
   847 	  labelMap = writers[i].second;
   848 	  forceLabelMap = false;
   849 	  break;
   850 	}
   851       }
   852       os << "\t\t";
   853       if (forceLabelMap) {
   854 	os << "label\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::UEdgeIt it(graph); it != INVALID; ++it) {
   861 	nodeLabelWriter->write(os, graph.source(it));
   862 	os << '\t';
   863 	nodeLabelWriter->write(os, graph.target(it));
   864 	os << '\t';
   865 	if (forceLabelMap) {
   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 labels of 
   879     /// the edges.
   880     ///
   881     /// Returns true if the undirected edgeset can write the labels of the 
   882     /// undirected edges. It is possible only if an "label" named map was 
   883     /// written or the \c _forceLabelMap constructor parameter was true.
   884     bool isLabelWriter() const {
   885       return forceLabelMap || labelMap != 0;
   886     }
   887 
   888     /// \brief Write the label of the given undirected edge.
   889     ///
   890     /// It writes the label of the given undirected edge. If there was written 
   891     /// an "label" named map then it will write the map value belongs to the 
   892     /// undirected edge. Otherwise if the \c forceLabel parameter was true it 
   893     /// will write its id in the graph. 
   894     void writeLabel(std::ostream& os, const UEdge& item) const {
   895       if (forceLabelMap) {
   896 	os << graph.id(item);
   897       } else {
   898 	labelMap->write(os, item);
   899       }
   900     } 
   901 
   902     /// \brief Write the label of the given edge.
   903     ///
   904     /// It writes the label of the given edge. If there was written 
   905     /// an "label" named map then it will write the map value belongs to the 
   906     /// edge. Otherwise if the \c forceLabel 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 writeLabel(std::ostream& os, const Edge& item) const {
   910       if (graph.direction(item)) {
   911 	os << "+ ";
   912       } else {
   913 	os << "- ";
   914       }
   915       if (forceLabelMap) {
   916 	os << graph.id(item);
   917       } else {
   918 	labelMap->write(os, item);
   919       }
   920     } 
   921 
   922   private:
   923 
   924     typedef std::vector<std::pair<std::string, _writer_bits::
   925 				  MapWriterBase<UEdge>*> > MapWriters;
   926     MapWriters writers;
   927 
   928     _writer_bits::MapWriterBase<UEdge>* labelMap;
   929     bool forceLabelMap;
   930    
   931     const Graph& graph;   
   932     std::string name;
   933 
   934     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
   935   };
   936 
   937   /// \ingroup io_group
   938   /// \brief SectionWriter for writing named nodes.
   939   ///
   940   /// The nodes section's header line is \c \@nodes \c nodes_name, but the
   941   /// \c nodes_name may be empty.
   942   ///
   943   /// Each line in the section contains the name of the node and 
   944   /// then the node label. 
   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 _LabelWriter
   958     /// will write the nodes' label what can be a nodeset writer.
   959     template <typename _LabelWriter>
   960     NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
   961 	       const std::string& _name = std::string()) 
   962       : Parent(_writer), name(_name) {
   963       checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
   964       labelWriter.reset(new _writer_bits::LabelWriter<Node, _LabelWriter>
   965                         (_labelWriter));
   966     }
   967 
   968 
   969     /// \brief Destructor.
   970     ///
   971     /// Destructor for NodeWriter.
   972     virtual ~NodeWriter() {}
   973 
   974   private:
   975     NodeWriter(const NodeWriter&);
   976     void operator=(const NodeWriter&);
   977 
   978   public:
   979 
   980     /// \brief Add a node writer command for the NodeWriter.
   981     ///
   982     /// Add a node writer command for the NodeWriter.
   983     void writeNode(const std::string& name, const Node& item) {
   984       writers.push_back(make_pair(name, &item));
   985     }
   986 
   987   protected:
   988 
   989     /// \brief The header of the section.
   990     ///
   991     /// It gives back the header of the section.
   992     virtual std::string header() {
   993       return "@nodes " + name;
   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 (!labelWriter->isLabelWriter()) {
  1001 	throw DataFormatError("Cannot find nodeset or label map");
  1002       }
  1003       for (int i = 0; i < (int)writers.size(); ++i) {
  1004 	os << writers[i].first << ' ';
  1005 	labelWriter->write(os, *(writers[i].second));
  1006 	os << std::endl;
  1007       }
  1008     }
  1009     
  1010   private:
  1011 
  1012     std::string name;
  1013 
  1014     typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
  1015     NodeWriters writers;
  1016     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
  1017   };
  1018 
  1019   /// \ingroup io_group
  1020   /// \brief SectionWriter for writing named edges.
  1021   ///
  1022   /// The edges section's header line is \c \@edges \c edges_name, but the
  1023   /// \c edges_name may be empty.
  1024   ///
  1025   /// Each line in the section contains the name of the edge and 
  1026   /// then the edge label. 
  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 _LabelWriter
  1040     /// will write the edges' label what can be a edgeset writer.
  1041     template <typename _LabelWriter>
  1042     EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
  1043 	       const std::string& _name = std::string()) 
  1044       : Parent(_writer), name(_name) {
  1045       checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
  1046       labelWriter.reset(new _writer_bits::LabelWriter<Edge, _LabelWriter>(_labelWriter));
  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 The header of the section.
  1069     ///
  1070     /// It gives back the header of the section.
  1071     virtual std::string header() {
  1072       return "@edges " + name;
  1073     }
  1074 
  1075     /// \brief  Writer function of the section.
  1076     ///
  1077     /// Write the content of the section.
  1078     virtual void write(std::ostream& os) {
  1079       if (!labelWriter->isLabelWriter()) {
  1080 	throw DataFormatError("Cannot find edgeset or label map");
  1081       }
  1082       for (int i = 0; i < (int)writers.size(); ++i) {
  1083 	os << writers[i].first << ' ';
  1084 	labelWriter->write(os, *(writers[i].second));
  1085 	os << std::endl;
  1086       }
  1087     }
  1088     
  1089   private:
  1090 
  1091     std::string name;
  1092 
  1093     typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
  1094     EdgeWriters writers;
  1095 
  1096     std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
  1097   };
  1098 
  1099   /// \ingroup io_group
  1100   /// \brief SectionWriter for writing named undirected edges.
  1101   ///
  1102   /// The undirected edges section's header line is \c \@uedges 
  1103   /// \c uedges_name, but the \c uedges_name may be empty.
  1104   ///
  1105   /// Each line in the section contains the name of the undirected edge and 
  1106   /// then the undirected edge label. 
  1107   ///
  1108   /// \relates LemonWriter
  1109   template <typename _Graph>
  1110   class UEdgeWriter : public LemonWriter::SectionWriter {
  1111     typedef LemonWriter::SectionWriter Parent;
  1112     typedef _Graph Graph;
  1113     typedef typename Graph::Node Node;
  1114     typedef typename Graph::Edge Edge;
  1115     typedef typename Graph::UEdge UEdge;
  1116   public:
  1117     
  1118     /// \brief Constructor.
  1119     ///
  1120     /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
  1121     /// attach it into the given LemonWriter. The given \c _LabelWriter
  1122     /// will write the undirected edges' label what can be an undirected 
  1123     /// edgeset writer.
  1124     template <typename _LabelWriter>
  1125     UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
  1126 	       const std::string& _name = std::string()) 
  1127       : Parent(_writer), name(_name) {
  1128       checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
  1129       checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
  1130       uEdgeLabelWriter.reset(new _writer_bits::
  1131 			      LabelWriter<UEdge, _LabelWriter>(_labelWriter));
  1132       edgeLabelWriter.reset(new _writer_bits::
  1133 			 LabelWriter<Edge, _LabelWriter>(_labelWriter));
  1134     }
  1135 
  1136     /// \brief Destructor.
  1137     ///
  1138     /// Destructor for UEdgeWriter.
  1139     virtual ~UEdgeWriter() {}
  1140   private:
  1141     UEdgeWriter(const UEdgeWriter&);
  1142     void operator=(const UEdgeWriter&);
  1143 
  1144   public:
  1145 
  1146     /// \brief Add an edge writer command for the UEdgeWriter.
  1147     ///
  1148     /// Add an edge writer command for the UEdgeWriter.
  1149     void writeEdge(const std::string& name, const Edge& item) {
  1150       edgeWriters.push_back(make_pair(name, &item));
  1151     }
  1152 
  1153     /// \brief Add an undirected edge writer command for the UEdgeWriter.
  1154     ///
  1155     /// Add an undirected edge writer command for the UEdgeWriter.
  1156     void writeUEdge(const std::string& name, const UEdge& item) {
  1157       uEdgeWriters.push_back(make_pair(name, &item));
  1158     }
  1159 
  1160   protected:
  1161 
  1162     /// \brief The header of the section.
  1163     ///
  1164     /// It gives back the header of the section.
  1165     virtual std::string header() {
  1166       return "@uedges " + name;
  1167     }
  1168 
  1169     /// \brief  Writer function of the section.
  1170     ///
  1171     /// Write the content of the section.
  1172     virtual void write(std::ostream& os) {
  1173       if (!edgeLabelWriter->isLabelWriter()) {
  1174 	throw DataFormatError("Cannot find undirected edgeset or label map");
  1175       }
  1176       if (!uEdgeLabelWriter->isLabelWriter()) {
  1177 	throw DataFormatError("Cannot find undirected edgeset or label map");
  1178       }
  1179       for (int i = 0; i < (int)uEdgeWriters.size(); ++i) {
  1180 	os << uEdgeWriters[i].first << ' ';
  1181 	uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
  1182 	os << std::endl;
  1183       }
  1184       for (int i = 0; i < (int)edgeWriters.size(); ++i) {
  1185 	os << edgeWriters[i].first << ' ';
  1186 	edgeLabelWriter->write(os, *(edgeWriters[i].second));
  1187 	os << std::endl;
  1188       }
  1189     }
  1190     
  1191   private:
  1192 
  1193     std::string name;
  1194 
  1195     typedef std::vector<std::pair<std::string, 
  1196 				  const UEdge*> > UEdgeWriters;
  1197     UEdgeWriters uEdgeWriters;
  1198     std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
  1199 
  1200     typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
  1201     EdgeWriters edgeWriters;
  1202     std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
  1203 
  1204   };
  1205 
  1206   /// \ingroup io_group
  1207   /// \brief SectionWriter for attributes.
  1208   ///
  1209   /// The lemon format can store multiple attribute set. Each set has
  1210   /// the header line \c \@attributes \c attributes_name, but the 
  1211   /// attributeset_name may be empty.
  1212   ///
  1213   /// The attributeset section contains several lines. Each of them starts
  1214   /// with the name of attribute and then the value.
  1215   ///
  1216   /// \relates LemonWriter
  1217   template <typename _Traits = DefaultWriterTraits>
  1218   class AttributeWriter : public LemonWriter::SectionWriter {
  1219     typedef LemonWriter::SectionWriter Parent;
  1220     typedef _Traits Traits; 
  1221   public:
  1222     /// \brief Constructor.
  1223     ///
  1224     /// Constructor for AttributeWriter. It creates the AttributeWriter and
  1225     /// attach it into the given LemonWriter.
  1226     AttributeWriter(LemonWriter& _writer, 
  1227 		    const std::string& _name = std::string()) 
  1228       : Parent(_writer), name(_name) {}
  1229 
  1230     /// \brief Destructor.
  1231     ///
  1232     /// Destructor for AttributeWriter.
  1233     virtual ~AttributeWriter() {
  1234       typename Writers::iterator it;
  1235       for (it = writers.begin(); it != writers.end(); ++it) {
  1236 	delete it->second;
  1237       }
  1238     }
  1239 
  1240   private:
  1241     AttributeWriter(const AttributeWriter&);
  1242     void operator=(AttributeWriter&);
  1243 
  1244   public:
  1245     /// \brief Add an attribute writer command for the writer.
  1246     ///
  1247     /// Add an attribute writer command for the writer.
  1248     template <typename Value>
  1249     AttributeWriter& writeAttribute(const std::string& name, 
  1250 				    const Value& value) {
  1251       return 
  1252 	writeAttribute<typename Traits::template Writer<Value> >(name, value);
  1253     }
  1254 
  1255     /// \brief Add an attribute writer command for the writer.
  1256     ///
  1257     /// Add an attribute writer command for the writer.
  1258     template <typename Writer, typename Value>
  1259     AttributeWriter& writeAttribute(const std::string& name, 
  1260 				    const Value& value,
  1261 				    const Writer& writer = Writer()) {
  1262       checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
  1263       writers.push_back(make_pair(name, new _writer_bits::
  1264 				  ValueWriter<Value, Writer>(value, writer)));
  1265       return *this;
  1266     }
  1267 
  1268   protected:
  1269 
  1270     /// \brief The header of section.
  1271     ///
  1272     /// It gives back the header of the section.
  1273     std::string header() {
  1274       return "@attributes " + name;
  1275     }
  1276 
  1277     /// \brief  Writer function of the section.
  1278     ///
  1279     /// Write the content of the section.
  1280     void write(std::ostream& os) {
  1281       typename Writers::iterator it;
  1282       for (it = writers.begin(); it != writers.end(); ++it) {
  1283 	os << it->first << ' ';
  1284 	it->second->write(os);
  1285 	os << std::endl;
  1286       }
  1287     }    
  1288 
  1289   private:
  1290     std::string name;
  1291 
  1292     typedef std::vector<std::pair<std::string, 
  1293 				  _writer_bits::ValueWriterBase*> > Writers;
  1294     Writers writers;  
  1295   };
  1296 
  1297 
  1298 }
  1299 #endif