lemon/lemon_writer.h
author kpeter
Thu, 13 Sep 2007 22:05:32 +0000
changeset 2470 46818ce27a60
parent 2414 9e80927b7921
child 2502 9c23c3762bc5
permissions -rw-r--r--
Small bug fixes.
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 ///\ingroup lemon_io
    20 ///\file
    21 ///\brief Lemon Format writer.
    22 
    23 #ifndef LEMON_LEMON_WRITER_H
    24 #define LEMON_LEMON_WRITER_H
    25 
    26 #include <iostream>
    27 #include <fstream>
    28 #include <string>
    29 #include <vector>
    30 #include <algorithm>
    31 #include <map>
    32 #include <memory>
    33 
    34 #include <lemon/error.h>
    35 #include <lemon/bits/invalid.h>
    36 #include <lemon/graph_utils.h>
    37 #include <lemon/bits/item_writer.h>
    38 #include <lemon/bits/utility.h>
    39 #include <lemon/maps.h>
    40 #include <lemon/dim2.h>
    41 
    42 #include <lemon/concept_check.h>
    43 #include <lemon/concepts/maps.h>
    44 
    45 
    46 namespace lemon {
    47 
    48   namespace _writer_bits {
    49     
    50     template <typename T>
    51     bool operator<(T, T) {
    52       throw DataFormatError("Label is not comparable");
    53     }
    54 
    55     template <typename T>
    56     struct Less {
    57       bool operator()(const T& p, const T& q) const {
    58 	return p < q;
    59       }
    60     };
    61 
    62     template <typename Map>
    63     struct ComposeLess {
    64       ComposeLess(const Map& _map) : map(_map), less() {}
    65 
    66       bool operator()(const typename Map::Key& p, 
    67                       const typename Map::Key& q) const {
    68 	return less(map[p], map[q]);
    69       }
    70       const Map& map;
    71       Less<typename Map::Value> less;
    72     };
    73 
    74     template <typename UGraph, typename Map>
    75     struct UEdgeComposeLess {
    76       UEdgeComposeLess(const UGraph& _ugraph, const Map& _map) 
    77 	: ugraph(_ugraph), map(_map), less() {}
    78 
    79       bool operator()(const typename UGraph::Edge& p, 
    80                       const typename UGraph::Edge& q) const {
    81 	return p != q ? less(map[p], map[q]) : 
    82 	  (!ugraph.direction(p) && ugraph.direction(q));
    83       }
    84 
    85       const UGraph& ugraph;
    86       const Map& map;
    87       Less<typename Map::Value> less;
    88     };
    89 
    90     template <typename Item>
    91     class ItemLabelWriter {
    92     public:
    93 
    94       bool isLabelWriter() { return true; }
    95 
    96       void writeLabel(std::ostream&, const Item&) {}
    97       
    98       template <class _ItemLabelWriter>
    99       struct Constraints {
   100 	void constraints() {
   101 	  bool b = writer.isLabelWriter();
   102 	  ignore_unused_variable_warning(b);
   103 	  writer.writeLabel(os, item);
   104 	}
   105 	_ItemLabelWriter& writer;
   106 	std::ostream& os;
   107 	const Item& item;
   108       };
   109 
   110     };
   111 
   112     template <typename Item>
   113     class ItemWriter {
   114     public:
   115 
   116       void write(std::ostream&, const Item&) {}
   117       
   118       template <class _ItemWriter>
   119       struct Constraints {
   120 	void constraints() {
   121 	  writer.write(os, item);
   122 	}
   123 	_ItemWriter& writer;
   124 	std::ostream& os;
   125 	const Item& item;
   126       };
   127 
   128     };
   129 
   130     template <typename Map>
   131     struct Ref { typedef const Map& Type; };
   132 
   133     template <typename Graph, typename Map>
   134     class ForwardComposeMap {
   135     public:
   136       typedef typename Graph::UEdge Key;
   137       typedef typename Map::Value Value;
   138 
   139       ForwardComposeMap(const Graph& _graph, const Map& _map) 
   140 	: graph(_graph), map(_map) {}
   141       
   142       Value operator[](const Key& key) const {
   143 	return map[graph.direct(key, true)];
   144       }
   145 
   146     private:
   147       typename Ref<Map>::Type map;
   148       const Graph& graph;
   149     };
   150 
   151     template <typename Graph, typename Map>
   152     ForwardComposeMap<Graph, Map>
   153     forwardComposeMap(const Graph& graph, const Map& map) {
   154       return ForwardComposeMap<Graph, Map>(graph, map);
   155     }
   156 
   157     template <typename Graph, typename Map>
   158     class BackwardComposeMap {
   159     public:
   160       typedef typename Graph::UEdge Key;
   161       typedef typename Map::Value Value;
   162 
   163       BackwardComposeMap(const Graph& _graph, const Map& _map) 
   164 	: graph(_graph), map(_map) {}
   165       
   166       Value operator[](const Key& key) const {
   167 	return map[graph.direct(key, false)];
   168       }
   169 
   170     private:
   171       typename Ref<Map>::Type map;
   172       const Graph& graph;
   173     };
   174 
   175     template <typename Graph, typename Map>
   176     BackwardComposeMap<Graph, Map>
   177     backwardComposeMap(const Graph& graph, const Map& map) {
   178       return BackwardComposeMap<Graph, Map>(graph, map);
   179     }
   180 
   181     template <typename Graph, typename Map>
   182     struct Ref<ForwardComposeMap<Graph, Map> > { 
   183       typedef ForwardComposeMap<Graph, Map> Type;
   184     };
   185 
   186     template <typename Graph, typename Map>
   187     struct Ref<BackwardComposeMap<Graph, Map> > { 
   188       typedef BackwardComposeMap<Graph, Map> Type; 
   189     };
   190 
   191     template <typename Map>
   192     struct Ref<dim2::XMap<Map> > { 
   193       typedef dim2::XMap<Map> Type;
   194     };
   195     template <typename Map>
   196     struct Ref<dim2::ConstXMap<Map> > { 
   197       typedef dim2::ConstXMap<Map> Type;
   198     };
   199 
   200     template <typename Map>
   201     struct Ref<dim2::YMap<Map> > { 
   202       typedef dim2::YMap<Map> Type;
   203     };
   204     template <typename Map>
   205     struct Ref<dim2::ConstYMap<Map> > { 
   206       typedef dim2::ConstYMap<Map> Type;
   207     };
   208 
   209 
   210     template <typename _Item>    
   211     class MapWriterBase {
   212     public:
   213       typedef _Item Item;
   214 
   215       virtual ~MapWriterBase() {}
   216 
   217       virtual void write(std::ostream& os, const Item& item) const = 0;
   218       virtual void sort(std::vector<Item>&) const = 0;
   219     };
   220 
   221 
   222     template <typename _Item, typename _Map, typename _Writer>
   223     class MapWriter : public MapWriterBase<_Item> {
   224     public:
   225       typedef _Map Map;
   226       typedef _Writer Writer;
   227       typedef typename Writer::Value Value;
   228       typedef _Item Item;
   229       
   230       typename _writer_bits::Ref<Map>::Type map;
   231       Writer writer;
   232 
   233       MapWriter(const Map& _map, const Writer& _writer) 
   234 	: map(_map), writer(_writer) {}
   235 
   236       virtual ~MapWriter() {}
   237 
   238       virtual void write(std::ostream& os, const Item& item) const {
   239 	Value value = map[item];
   240 	writer.write(os, value);
   241       }
   242 
   243       virtual void sort(std::vector<Item>& items) const {
   244         ComposeLess<Map> less(map);
   245         std::sort(items.begin(), items.end(), less);
   246       }
   247 
   248     };
   249 
   250     template <typename _UGraph>    
   251     class UEdgeMapWriterBase {
   252     public:
   253       typedef typename _UGraph::Edge Edge;
   254       typedef typename _UGraph::UEdge UEdge;
   255 
   256       typedef UEdge Item;
   257 
   258       virtual ~UEdgeMapWriterBase() {}
   259 
   260       virtual void write(std::ostream& os, const Item& item) const = 0;
   261       virtual void sort(const _UGraph&, std::vector<Edge>&) const = 0;
   262       virtual void sort(std::vector<UEdge>&) const = 0;
   263     };
   264 
   265 
   266     template <typename _UGraph, typename _Map, typename _Writer>
   267     class UEdgeMapWriter : public UEdgeMapWriterBase<_UGraph> {
   268     public:
   269       typedef _Map Map;
   270       typedef _Writer Writer;
   271       typedef typename Writer::Value Value;
   272 
   273       typedef typename _UGraph::Edge Edge;
   274       typedef typename _UGraph::UEdge UEdge;
   275       typedef UEdge Item;
   276       
   277       typename _writer_bits::Ref<Map>::Type map;
   278       Writer writer;
   279 
   280       UEdgeMapWriter(const Map& _map, const Writer& _writer) 
   281 	: map(_map), writer(_writer) {}
   282 
   283       virtual ~UEdgeMapWriter() {}
   284 
   285       virtual void write(std::ostream& os, const Item& item) const {
   286 	Value value = map[item];
   287 	writer.write(os, value);
   288       }
   289 
   290       virtual void sort(const _UGraph& ugraph, std::vector<Edge>& items) const {
   291         UEdgeComposeLess<_UGraph, Map> less(ugraph, map);
   292         std::sort(items.begin(), items.end(), less);
   293       }
   294 
   295       virtual void sort(std::vector<UEdge>& items) const {
   296         ComposeLess<Map> less(map);
   297         std::sort(items.begin(), items.end(), less);
   298       }
   299 
   300     };
   301 
   302 
   303     class ValueWriterBase {
   304     public:
   305       virtual ~ValueWriterBase() {}
   306       virtual void write(std::ostream&) = 0;
   307     };
   308 
   309     template <typename _Value, typename _Writer>
   310     class ValueWriter : public ValueWriterBase {
   311     public:
   312       typedef _Value Value;
   313       typedef _Writer Writer;
   314 
   315       ValueWriter(const Value& _value, const Writer& _writer)
   316  	: value(_value), writer(_writer) {}
   317 
   318       virtual void write(std::ostream& os) {
   319 	writer.write(os, value);
   320       }
   321     private:
   322       const Value& value;
   323       Writer writer;
   324     };
   325     
   326 
   327     template <typename _Item>
   328     class LabelWriterBase {
   329     public:
   330       typedef _Item Item;
   331       virtual ~LabelWriterBase() {}
   332       virtual void write(std::ostream&, const Item&) const = 0;
   333       virtual void sort(std::vector<Item>&) const = 0;
   334       virtual bool isLabelWriter() const = 0;
   335       virtual LabelWriterBase* clone() const = 0;
   336     };
   337 
   338     template <typename _Item, typename _BoxedLabelWriter>
   339     class LabelWriter : public LabelWriterBase<_Item> {
   340     public:
   341       typedef _Item Item;
   342       typedef _BoxedLabelWriter BoxedLabelWriter;
   343 
   344       const BoxedLabelWriter& labelWriter;
   345 
   346       LabelWriter(const BoxedLabelWriter& _labelWriter) 
   347 	: labelWriter(_labelWriter) {}
   348 
   349       virtual void write(std::ostream& os, const Item& item) const {
   350 	labelWriter.writeLabel(os, item);
   351       }
   352       virtual void sort(std::vector<Item>& items) const {
   353 	labelWriter.sortByLabel(items);
   354       }
   355 
   356       virtual bool isLabelWriter() const {
   357 	return labelWriter.isLabelWriter();
   358       }
   359 
   360       virtual LabelWriter* clone() const {
   361 	return new LabelWriter(labelWriter);
   362       }
   363     };
   364 
   365   }
   366 
   367   /// \ingroup lemon_io
   368   /// \brief Lemon Format writer class.
   369   /// 
   370   /// The Lemon Format contains several sections. We do not want to
   371   /// determine what sections are in a lemon file we give only a framework
   372   /// to write a section oriented format.
   373   ///
   374   /// In the Lemon Format each section starts with a line contains a \c \@
   375   /// character on the first not white space position. This line is the
   376   /// header line of the section. Each next lines belong to this section
   377   /// while it does not starts with \c \@ character. This line can start a 
   378   /// new section or if it can close the file with the \c \@end line.
   379   /// The file format ignore the empty lines and it may contain comments
   380   /// started with a \c # character to the end of the line. 
   381   ///
   382   /// The framework provides an abstract LemonWriter::SectionWriter class
   383   /// what defines the interface of a SectionWriter. The SectionWriter
   384   /// has the \c header() member function what gives back the header of the
   385   /// section. After that it will be called the \c write() member which
   386   /// should write the content of the section.
   387   ///
   388   /// \relates GraphWriter
   389   /// \relates NodeSetWriter
   390   /// \relates EdgeSetWriter
   391   /// \relates NodesWriter
   392   /// \relates EdgesWriter
   393   /// \relates AttributeWriter
   394   class LemonWriter {
   395   public:
   396 
   397     /// \brief Abstract base class for writing a section.
   398     ///
   399     /// This class has an \c header() member function what gives back
   400     /// the header line of the section. The \c write() member should
   401     /// write the content of the section to the stream.
   402     class SectionWriter {
   403       friend class LemonWriter;
   404     protected:
   405       /// \brief Constructor for SectionWriter.
   406       ///
   407       /// Constructor for SectionWriter. It attach this writer to
   408       /// the given LemonWriter.
   409       SectionWriter(LemonWriter& writer) {
   410 	writer.attach(*this);
   411       }
   412       
   413       virtual ~SectionWriter() {}
   414 
   415       /// \brief The header of section.
   416       ///
   417       /// It gives back the header of the section.
   418       virtual std::string header() = 0;
   419 
   420       /// \brief Writer function of the section.
   421       ///
   422       /// Write the content of the section.
   423       virtual void write(std::ostream& os) = 0;
   424       
   425       /// \brief Gives back true when the section should be written.
   426       ///
   427       /// Gives back true when the section should be written.
   428       virtual bool valid() { return true; }
   429     };
   430 
   431     /// \brief Constructor for LemonWriter.
   432     ///
   433     /// Constructor for LemonWriter which writes to the given stream.
   434     LemonWriter(std::ostream& _os) 
   435       : os(&_os), own_os(false) {}
   436 
   437     /// \brief Constructor for LemonWriter.
   438     ///
   439     /// Constructor for LemonWriter which writes to the given file.
   440     LemonWriter(const std::string& filename) 
   441       : os(0), own_os(true) {
   442       os = new std::ofstream(filename.c_str());
   443     }
   444 
   445     /// \brief Desctructor for LemonWriter.
   446     ///
   447     /// Desctructor for LemonWriter.
   448     ~LemonWriter() {
   449       if (own_os) {
   450 	delete os;
   451       }
   452     }
   453 
   454   private:
   455     LemonWriter(const LemonWriter&);
   456     void operator=(const LemonWriter&);
   457 
   458     void attach(SectionWriter& writer) {
   459       writers.push_back(&writer);
   460     }
   461 
   462   public:
   463 
   464     /// \brief Executes the LemonWriter.
   465     /// 
   466     /// It executes the LemonWriter.
   467     void run() {
   468       SectionWriters::iterator it;
   469       for (it = writers.begin(); it != writers.end(); ++it) {
   470         if ((*it)->valid()) {
   471           *os << (*it)->header() << std::endl;
   472           (*it)->write(*os);
   473         }
   474       }
   475       *os << "@end" << std::endl;
   476     }
   477 
   478 
   479   private:
   480 
   481     std::ostream* os;
   482     bool own_os;
   483 
   484     typedef std::vector<SectionWriter*> SectionWriters;
   485     SectionWriters writers;
   486 
   487   };
   488 
   489   /// \ingroup section_io
   490   /// \brief SectionWriter for writing a graph's nodeset.
   491   ///
   492   /// The lemon format can store multiple graph nodesets with several maps.
   493   /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but 
   494   /// the \c nodeset_name may be empty.
   495   ///
   496   /// The first line of the section contains the names of the maps separated
   497   /// with white spaces. Each next lines describes a node in the nodeset, and
   498   /// contains the mapped values for each map.
   499   ///
   500   /// If the nodeset contains an \c "label" named map then it will be regarded
   501   /// as label map. This map should contain only unique values and when the 
   502   /// \c writeLabel() member will be called with a node it will write it's 
   503   /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
   504   /// then the label map will be the id in the graph. In addition if the
   505   /// the \c _forceSort is true then the writer will write the edges
   506   /// sorted by the labels.
   507   ///
   508   /// \relates LemonWriter
   509   template <typename _Graph, typename _Traits = DefaultWriterTraits>
   510   class NodeSetWriter : public LemonWriter::SectionWriter {
   511     typedef LemonWriter::SectionWriter Parent;
   512   public:
   513 
   514     typedef _Graph Graph;
   515     typedef _Traits Traits;
   516     typedef typename Graph::Node Node;
   517 
   518     /// \brief Constructor.
   519     ///
   520     /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
   521     /// attach it into the given LemonWriter. If the \c _forceLabelMap
   522     /// parameter is true then the writer will write own label map when
   523     /// the user does not give "label" named map. In addition if the
   524     /// the \c _forceSort is true then the writer will write the edges
   525     /// sorted by the labels.
   526     NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   527 		  const std::string& _name = std::string(), 
   528 		  bool _forceLabelMap = true, bool _forceSort = true) 
   529       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), 
   530 	forceSort(_forceSort), graph(_graph), name(_name) {}
   531 
   532     /// \brief Destructor.
   533     ///
   534     /// Destructor for NodeSetWriter.
   535     virtual ~NodeSetWriter() {
   536       typename MapWriters::iterator it;
   537       for (it = writers.begin(); it != writers.end(); ++it) {
   538 	delete it->second;
   539       }
   540     }
   541 
   542   private:
   543     NodeSetWriter(const NodeSetWriter&);
   544     void operator=(const NodeSetWriter&);
   545   
   546   public:
   547 
   548     /// \brief Add a new node map writer command for the writer.
   549     ///
   550     /// Add a new node map writer command for the writer.
   551     template <typename Map>
   552     NodeSetWriter& writeNodeMap(std::string label, const Map& map) {
   553       return writeNodeMap<typename Traits::
   554 	template Writer<typename Map::Value>, Map>(label, map);
   555     }
   556 
   557     /// \brief Add a new node map writer command for the writer.
   558     ///
   559     /// Add a new node map writer command for the writer.
   560     template <typename ItemWriter, typename Map>
   561     NodeSetWriter& writeNodeMap(std::string label, const Map& map, 
   562 			    const ItemWriter& iw = ItemWriter()) {
   563       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   564       checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
   565       writers.push_back(
   566 	make_pair(label, new _writer_bits::
   567 		  MapWriter<Node, Map, ItemWriter>(map, iw)));
   568       return *this;
   569     }
   570 
   571   protected:
   572 
   573     /// \brief The header of the section.
   574     ///
   575     /// It gives back the header of the section.
   576     virtual std::string header() {
   577       return "@nodeset " + name;
   578     }
   579 
   580     /// \brief  Writer function of the section.
   581     ///
   582     /// Write the content of the section.
   583     virtual void write(std::ostream& os) {
   584       for (int i = 0; i < int(writers.size()); ++i) {
   585 	if (writers[i].first == "label") {
   586 	  labelMap = writers[i].second;
   587 	  forceLabelMap = false;
   588 	  break;
   589 	}
   590       }
   591       std::vector<Node> items;
   592       for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
   593         items.push_back(it);
   594       }
   595       if (forceSort) {
   596         if (labelMap) {
   597           labelMap->sort(items);
   598         } else {
   599           typedef IdMap<Graph, Node> Map;
   600           Map map(graph);
   601           _writer_bits::ComposeLess<Map> less(map);
   602           std::sort(items.begin(), items.end(), less);
   603         }
   604       }
   605       if (forceLabelMap) {
   606 	os << "label\t";
   607       }
   608       for (int i = 0; i < int(writers.size()); ++i) {
   609 	os << writers[i].first << '\t';
   610       }
   611       os << std::endl;
   612       for (typename std::vector<Node>::iterator it = items.begin();
   613            it != items.end(); ++it) {
   614 	if (forceLabelMap) {
   615 	  os << graph.id(*it) << '\t';
   616 	}
   617 	for (int i = 0; i < int(writers.size()); ++i) {
   618 	  writers[i].second->write(os, *it);
   619 	  os << '\t';
   620 	}
   621 	os << std::endl;
   622       }
   623     }
   624 
   625   public:
   626 
   627     /// \brief Returns true if the nodeset can write the labels of the nodes.
   628     ///
   629     /// Returns true if the nodeset can write the labels of the nodes.
   630     /// It is possible only if a "label" named map was written or the 
   631     /// \c _forceLabelMap constructor parameter was true.
   632     bool isLabelWriter() const {
   633       return labelMap != 0 || forceLabelMap;
   634     }
   635 
   636     /// \brief Write the label of the given node.
   637     ///
   638     /// It writes the label of the given node. If there was written a "label"
   639     /// named map then it will write the map value belongs to the node.
   640     /// Otherwise if the \c forceLabel parameter was true it will write
   641     /// its label in the graph. 
   642     void writeLabel(std::ostream& os, const Node& item) const {
   643       if (forceLabelMap) {
   644 	os << graph.id(item);
   645       } else {
   646 	labelMap->write(os, item);
   647       }
   648     }
   649 
   650     /// \brief Sorts the given node vector by label.
   651     ///
   652     /// Sorts the given node vector by label. If there was written an
   653     /// "label" named map then the vector will be sorted by the values
   654     /// of this map. Otherwise if the \c forceLabel parameter was true
   655     /// it will be sorted by its id in the graph.
   656     void sortByLabel(std::vector<Node>& nodes) const {
   657       if (labelMap) {
   658 	labelMap->sort(nodes);
   659       } else {
   660 	typedef IdMap<Graph, Node> Map;
   661 	Map map(graph);
   662 	_writer_bits::ComposeLess<Map> less(map);
   663 	std::sort(nodes.begin(), nodes.end(), less);
   664       }
   665     }
   666 
   667   private:
   668 
   669     typedef std::vector<std::pair<std::string, _writer_bits::
   670 				  MapWriterBase<Node>*> > MapWriters;
   671     MapWriters writers;
   672 
   673     _writer_bits::MapWriterBase<Node>* labelMap;
   674     bool forceLabelMap;
   675     bool forceSort;
   676    
   677     const Graph& graph;   
   678     std::string name;
   679 
   680   };
   681 
   682   /// \ingroup section_io
   683   /// \brief SectionWriter for writing a graph's edgesets.
   684   ///
   685   /// The lemon format can store multiple graph edgesets with several maps. 
   686   /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but 
   687   /// the \c edgeset_name may be empty.
   688   ///
   689   /// The first line of the section contains the names of the maps separated
   690   /// with white spaces. Each next lines describes a edge in the edgeset. The
   691   /// line contains the source and the target nodes' label and the mapped 
   692   /// values for each map.
   693   ///
   694   /// If the edgeset contains an \c "label" named map then it will be regarded
   695   /// as label map. This map should contain only unique values and when the 
   696   /// \c writeLabel() member will be called with an edge it will write it's 
   697   /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
   698   /// then the label map will be the id in the graph. In addition if the
   699   /// the \c _forceSort is true then the writer will write the edges
   700   /// sorted by the labels.
   701   ///
   702   /// The edgeset writer needs a node label writer to identify which nodes
   703   /// have to be connected. If a NodeSetWriter can write the nodes' label,
   704   /// it will be able to use with this class.
   705   ///
   706   /// \relates LemonWriter
   707   template <typename _Graph, typename _Traits = DefaultWriterTraits>
   708   class EdgeSetWriter : public LemonWriter::SectionWriter {
   709     typedef LemonWriter::SectionWriter Parent;
   710   public:
   711 
   712     typedef _Graph Graph;
   713     typedef _Traits Traits;
   714     typedef typename Graph::Node Node;
   715     typedef typename Graph::Edge Edge;
   716 
   717     /// \brief Constructor.
   718     ///
   719     /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter
   720     /// and attach it into the given LemonWriter. It will write node
   721     /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
   722     /// parameter is true then the writer will write own label map if
   723     /// the user does not give "label" named map. In addition if the
   724     /// the \c _forceSort is true then the writer will write the
   725     /// edges sorted by the labels.
   726     template <typename NodeLabelWriter>
   727     EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   728 		  const NodeLabelWriter& _nodeLabelWriter, 
   729 		  const std::string& _name = std::string(),
   730 		  bool _forceLabelMap = true, bool _forceSort = true)
   731       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
   732 	forceSort(_forceSort), graph(_graph), name(_name) {
   733       checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
   734       nodeLabelWriter.reset(new _writer_bits::
   735 			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
   736     } 
   737 
   738     /// \brief Destructor.
   739     ///
   740     /// Destructor for EdgeSetWriter.
   741     virtual ~EdgeSetWriter() {
   742       typename MapWriters::iterator it;
   743       for (it = writers.begin(); it != writers.end(); ++it) {
   744 	delete it->second;
   745       }
   746     }
   747 
   748   private:
   749     EdgeSetWriter(const EdgeSetWriter&);
   750     void operator=(const EdgeSetWriter&);
   751 
   752   public:
   753 
   754     /// \brief Add a new edge map writer command for the writer.
   755     ///
   756     /// Add a new edge map writer command for the writer.
   757     template <typename Map>
   758     EdgeSetWriter& writeEdgeMap(std::string label, const Map& map) {
   759       return writeEdgeMap<typename Traits::
   760 	template Writer<typename Map::Value>, Map>(label, map);
   761     }
   762 
   763     /// \brief Add a new edge map writer command for the writer.
   764     ///
   765     /// Add a new edge map writer command for the writer.
   766     template <typename ItemWriter, typename Map>
   767     EdgeSetWriter& writeEdgeMap(std::string label, const Map& map, 
   768 			    const ItemWriter& iw = ItemWriter()) {
   769       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
   770       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
   771       writers.push_back(
   772 	make_pair(label, new _writer_bits::
   773 		  MapWriter<Edge, Map, ItemWriter>(map, iw)));
   774       return *this;
   775     }
   776 
   777   protected:
   778 
   779     /// \brief The header of the section.
   780     ///
   781     /// It gives back the header of the section.
   782     virtual std::string header() {
   783       return "@edgeset " + name;
   784     }
   785 
   786     /// \brief  Writer function of the section.
   787     ///
   788     /// Write the content of the section.
   789     virtual void write(std::ostream& os) {
   790       if (!nodeLabelWriter->isLabelWriter()) {
   791 	throw DataFormatError("Cannot find nodeset or label map");
   792       }
   793       for (int i = 0; i < int(writers.size()); ++i) {
   794 	if (writers[i].first == "label") {
   795 	  labelMap = writers[i].second;
   796 	  forceLabelMap = false;
   797 	  break;
   798 	}
   799       }
   800       std::vector<Edge> items;
   801       for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
   802         items.push_back(it);
   803       }
   804       if (forceSort) {
   805         if (labelMap) {
   806           labelMap->sort(items);
   807         } else {
   808           typedef IdMap<Graph, Edge> Map;
   809           Map map(graph);
   810           _writer_bits::ComposeLess<Map> less(map);
   811           std::sort(items.begin(), items.end(), less);
   812         }
   813       }
   814       os << "\t\t";
   815       if (forceLabelMap) {
   816 	os << "label\t";
   817       }
   818       for (int i = 0; i < int(writers.size()); ++i) {
   819 	os << writers[i].first << '\t';
   820       }
   821       os << std::endl;
   822       for (typename std::vector<Edge>::iterator it = items.begin();
   823            it != items.end(); ++it) {
   824 	nodeLabelWriter->write(os, graph.source(*it));
   825 	os << '\t';
   826 	nodeLabelWriter->write(os, graph.target(*it));
   827 	os << '\t';
   828 	if (forceLabelMap) {
   829 	  os << graph.id(*it) << '\t';
   830 	}
   831 	for (int i = 0; i < int(writers.size()); ++i) {
   832 	  writers[i].second->write(os, *it);
   833 	  os << '\t';
   834 	}
   835 	os << std::endl;
   836       }
   837     }
   838 
   839   public:
   840 
   841     /// \brief Returns true if the edgeset can write the labels of the edges.
   842     ///
   843     /// Returns true if the edgeset can write the labels of the edges.
   844     /// It is possible only if a "label" named map was written or the 
   845     /// \c _forceLabelMap constructor parameter was true.
   846     bool isLabelWriter() const {
   847       return forceLabelMap || labelMap != 0;
   848     }
   849 
   850     /// \brief Write the label of the given edge.
   851     ///
   852     /// It writes the label of the given edge. If there was written a "label"
   853     /// named map then it will write the map value belongs to the edge.
   854     /// Otherwise if the \c forceLabel parameter was true it will write
   855     /// its label in the graph. 
   856     void writeLabel(std::ostream& os, const Edge& item) const {
   857       if (forceLabelMap) {
   858 	os << graph.id(item);
   859       } else {
   860 	labelMap->write(os, item);
   861       }
   862     } 
   863 
   864     /// \brief Sorts the given edge vector by label.
   865     ///
   866     /// Sorts the given edge vector by label. If there was written an
   867     /// "label" named map then the vector will be sorted by the values
   868     /// of this map. Otherwise if the \c forceLabel parameter was true
   869     /// it will be sorted by its id in the graph.
   870     void sortByLabel(std::vector<Edge>& edges) const {
   871       if (labelMap) {
   872 	labelMap->sort(edges);
   873       } else {
   874 	typedef IdMap<Graph, Edge> Map;
   875 	Map map(graph);
   876 	_writer_bits::ComposeLess<Map> less(map);
   877 	std::sort(edges.begin(), edges.end(), less);
   878       }
   879     }
   880 
   881   private:
   882 
   883     typedef std::vector<std::pair<std::string, _writer_bits::
   884 				  MapWriterBase<Edge>*> > MapWriters;
   885     MapWriters writers;
   886 
   887     _writer_bits::MapWriterBase<Edge>* labelMap;
   888     bool forceLabelMap;
   889     bool forceSort;
   890    
   891     const Graph& graph;   
   892     std::string name;
   893 
   894     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
   895   };
   896 
   897   /// \ingroup section_io
   898   /// \brief SectionWriter for writing a undirected edgeset.
   899   ///
   900   /// The lemon format can store multiple undirected edgesets with several 
   901   /// maps. The undirected edgeset section's header line is \c \@uedgeset 
   902   /// \c uedgeset_name, but the \c uedgeset_name may be empty.
   903   ///
   904   /// The first line of the section contains the names of the maps separated
   905   /// with white spaces. Each next lines describes an undirected edge in the 
   906   /// edgeset. The line contains the two connected nodes' label and the mapped 
   907   /// values for each undirected map.
   908   ///
   909   /// The section can handle the directed as a syntactical sugar. Two
   910   /// undirected edge map describes one directed edge map. This two maps
   911   /// are the forward map and the backward map and the names of this map
   912   /// is near the same just with a prefix \c '+' or \c '-' character 
   913   /// difference.
   914   ///
   915   /// If the edgeset contains an \c "label" named map then it will be
   916   /// regarded as label map. This map should contain only unique
   917   /// values and when the \c writeLabel() member will be called with
   918   /// an undirected edge it will write it's label. Otherwise if the \c
   919   /// _forceLabelMap constructor parameter is true then the label map
   920   /// will be the id in the graph.  In addition if the the \c
   921   /// _forceSort is true then the writer will write the edges sorted
   922   /// by the labels.
   923   ///
   924   /// The undirected edgeset writer needs a node label writer to identify 
   925   /// which nodes have to be connected. If a NodeSetWriter can write the 
   926   /// nodes' label, it will be able to use with this class.
   927   ///
   928   /// \relates LemonWriter
   929   template <typename _Graph, typename _Traits = DefaultWriterTraits>
   930   class UEdgeSetWriter : public LemonWriter::SectionWriter {
   931     typedef LemonWriter::SectionWriter Parent;
   932   public:
   933 
   934     typedef _Graph Graph;
   935     typedef _Traits Traits;
   936     typedef typename Graph::Node Node;
   937     typedef typename Graph::Edge Edge;
   938     typedef typename Graph::UEdge UEdge;
   939 
   940     /// \brief Constructor.
   941     ///
   942     /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
   943     /// and attach it into the given LemonWriter. It will write node
   944     /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
   945     /// parameter is true then the writer will write own label map if
   946     /// the user does not give "label" named map. In addition if the
   947     /// the \c _forceSort is true then the writer will write the
   948     /// edges sorted by the labels.
   949     template <typename NodeLabelWriter>
   950     UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   951 		       const NodeLabelWriter& _nodeLabelWriter, 
   952 		       const std::string& _name = std::string(),
   953 		       bool _forceLabelMap = true, bool _forceSort = true)
   954       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
   955 	forceSort(_forceSort), graph(_graph), name(_name) {
   956       checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
   957       nodeLabelWriter.reset(new _writer_bits::
   958 	LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
   959     } 
   960 
   961     /// \brief Destructor.
   962     ///
   963     /// Destructor for UEdgeSetWriter.
   964     virtual ~UEdgeSetWriter() {
   965       typename MapWriters::iterator it;
   966       for (it = writers.begin(); it != writers.end(); ++it) {
   967 	delete it->second;
   968       }
   969     }
   970 
   971   private:
   972     UEdgeSetWriter(const UEdgeSetWriter&);
   973     void operator=(const UEdgeSetWriter&);
   974 
   975   public:
   976 
   977     /// \brief Add a new undirected edge map writer command for the writer.
   978     ///
   979     /// Add a new undirected map writer command for the writer.
   980     template <typename Map>
   981     UEdgeSetWriter& writeUEdgeMap(std::string label, const Map& map) {
   982       return writeUEdgeMap<typename Traits::
   983 	template Writer<typename Map::Value>, Map>(label, map);
   984     }
   985 
   986     /// \brief Add a new undirected map writer command for the writer.
   987     ///
   988     /// Add a new undirected map writer command for the writer.
   989     template <typename ItemWriter, typename Map>
   990     UEdgeSetWriter& writeUEdgeMap(std::string label, const Map& map, 
   991                                   const ItemWriter& iw = ItemWriter()) {
   992       checkConcept<concepts::ReadMap<UEdge, typename Map::Value>, Map>();
   993       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
   994       writers.push_back(
   995 	make_pair(label, new _writer_bits::
   996 		  UEdgeMapWriter<Graph, Map, ItemWriter>(map, iw)));
   997       return *this;
   998     }
   999 
  1000     /// \brief Add a new directed edge map writer command for the writer.
  1001     ///
  1002     /// Add a new directed map writer command for the writer.
  1003     template <typename Map>
  1004     UEdgeSetWriter& writeEdgeMap(std::string label, const Map& map) {
  1005       return writeEdgeMap<typename Traits::
  1006 	template Writer<typename Map::Value>, Map>(label, map);
  1007     }
  1008 
  1009     /// \brief Add a new directed map writer command for the writer.
  1010     ///
  1011     /// Add a new directed map writer command for the writer.
  1012     template <typename ItemWriter, typename Map>
  1013     UEdgeSetWriter& writeEdgeMap(std::string label, const Map& map, 
  1014                                  const ItemWriter& iw = ItemWriter()) {
  1015       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
  1016       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
  1017       writeUEdgeMap("+" + label, 
  1018                     _writer_bits::forwardComposeMap(graph, map), iw);
  1019       writeUEdgeMap("-" + label, 
  1020                     _writer_bits::backwardComposeMap(graph, map), iw);
  1021       return *this;
  1022     }
  1023 
  1024   protected:
  1025 
  1026     /// \brief The header of the section.
  1027     ///
  1028     /// It gives back the header of the section.
  1029     virtual std::string header() {
  1030       return "@uedgeset " + name;
  1031     }
  1032 
  1033     /// \brief  Writer function of the section.
  1034     ///
  1035     /// Write the content of the section.
  1036     virtual void write(std::ostream& os) {
  1037       if (!nodeLabelWriter->isLabelWriter()) {
  1038 	throw DataFormatError("Cannot find nodeset or label map");
  1039       }
  1040       for (int i = 0; i < int(writers.size()); ++i) {
  1041 	if (writers[i].first == "label") {
  1042 	  labelMap = writers[i].second;
  1043 	  forceLabelMap = false;
  1044 	  break;
  1045 	}
  1046       }
  1047       std::vector<UEdge> items;
  1048       for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
  1049         items.push_back(it);
  1050       }
  1051       if (forceSort) {
  1052         if (labelMap) {
  1053           labelMap->sort(items);
  1054         } else {
  1055           typedef IdMap<Graph, UEdge> Map;
  1056           Map map(graph);
  1057           _writer_bits::ComposeLess<Map> less(map);
  1058           std::sort(items.begin(), items.end(), less);
  1059         }
  1060       }
  1061       os << "\t\t";
  1062       if (forceLabelMap) {
  1063 	os << "label\t";
  1064       }
  1065       for (int i = 0; i < int(writers.size()); ++i) {
  1066 	os << writers[i].first << '\t';
  1067       }
  1068       os << std::endl;
  1069       for (typename std::vector<UEdge>::iterator it = items.begin();
  1070            it != items.end(); ++it) {
  1071 	nodeLabelWriter->write(os, graph.source(*it));
  1072 	os << '\t';
  1073 	nodeLabelWriter->write(os, graph.target(*it));
  1074 	os << '\t';
  1075 	if (forceLabelMap) {
  1076 	  os << graph.id(*it) << '\t';
  1077 	}
  1078 	for (int i = 0; i < int(writers.size()); ++i) {
  1079 	  writers[i].second->write(os, *it);
  1080 	  os << '\t';
  1081 	}
  1082 	os << std::endl;
  1083       }
  1084     }
  1085 
  1086   public:
  1087 
  1088     /// \brief Returns true if the undirected edgeset can write the labels of 
  1089     /// the edges.
  1090     ///
  1091     /// Returns true if the undirected edgeset can write the labels of the 
  1092     /// undirected edges. It is possible only if a "label" named map was 
  1093     /// written or the \c _forceLabelMap constructor parameter was true.
  1094     bool isLabelWriter() const {
  1095       return forceLabelMap || labelMap != 0;
  1096     }
  1097 
  1098     /// \brief Write the label of the given undirected edge.
  1099     ///
  1100     /// It writes the label of the given undirected edge. If there was written 
  1101     /// a "label" named map then it will write the map value belongs to the 
  1102     /// undirected edge. Otherwise if the \c forceLabel parameter was true it 
  1103     /// will write its id in the graph. 
  1104     void writeLabel(std::ostream& os, const UEdge& item) const {
  1105       if (forceLabelMap) {
  1106 	os << graph.id(item);
  1107       } else {
  1108 	labelMap->write(os, item);
  1109       }
  1110     } 
  1111 
  1112     /// \brief Write the label of the given edge.
  1113     ///
  1114     /// It writes the label of the given edge. If there was written 
  1115     /// a "label" named map then it will write the map value belongs to the 
  1116     /// edge. Otherwise if the \c forceLabel parameter was true it 
  1117     /// will write its id in the graph. If the edge is forward map
  1118     /// then its prefix character is \c '+' elsewhere \c '-'.
  1119     void writeLabel(std::ostream& os, const Edge& item) const {
  1120       if (graph.direction(item)) {
  1121 	os << "+";
  1122       } else {
  1123 	os << "-";
  1124       }
  1125       if (forceLabelMap) {
  1126 	os << graph.id(static_cast<const UEdge&>(item));
  1127       } else {
  1128 	labelMap->write(os, item);
  1129       }
  1130     } 
  1131 
  1132     /// \brief Sorts the given undirected edge vector by label.
  1133     ///
  1134     /// Sorts the given undirected edge vector by label. If there was
  1135     /// written a "label" named map then the vector will be sorted by
  1136     /// the values of this map. Otherwise if the \c forceLabel
  1137     /// parameter was true it will be sorted by its id in the graph.
  1138     void sortByLabel(std::vector<UEdge>& uedges) const {
  1139       if (labelMap) {
  1140 	labelMap->sort(uedges);
  1141       } else {
  1142 	typedef IdMap<Graph, UEdge> Map;
  1143 	Map map(graph);
  1144 	_writer_bits::ComposeLess<Map> less(map);
  1145 	std::sort(uedges.begin(), uedges.end(), less);
  1146       }
  1147     }
  1148 
  1149     /// \brief Sorts the given edge vector by label.
  1150     ///
  1151     /// Sorts the given edge vector by label. If there was written a
  1152     /// "label" named map then the vector will be sorted by the values
  1153     /// of this map. Otherwise if the \c forceLabel parameter was true
  1154     /// it will be sorted by its id in the graph.
  1155     void sortByLabel(std::vector<Edge>& edges) const {
  1156       if (labelMap) {
  1157 	labelMap->sort(graph, edges);
  1158       } else {
  1159 	typedef IdMap<Graph, Edge> Map;
  1160 	Map map(graph);
  1161 	_writer_bits::ComposeLess<Map> less(map);
  1162 	std::sort(edges.begin(), edges.end(), less);
  1163       }
  1164     }
  1165 
  1166   private:
  1167 
  1168     typedef std::vector<std::pair<std::string, _writer_bits::
  1169 				  UEdgeMapWriterBase<Graph>*> > MapWriters;
  1170     MapWriters writers;
  1171 
  1172     _writer_bits::UEdgeMapWriterBase<Graph>* labelMap;
  1173     bool forceLabelMap;
  1174     bool forceSort;
  1175    
  1176     const Graph& graph;   
  1177     std::string name;
  1178 
  1179     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
  1180   };
  1181 
  1182   /// \ingroup section_io
  1183   /// \brief SectionWriter for writing named nodes.
  1184   ///
  1185   /// The nodes section's header line is \c \@nodes \c nodes_name, but the
  1186   /// \c nodes_name may be empty.
  1187   ///
  1188   /// Each line in the section contains the name of the node and 
  1189   /// then the node label. 
  1190   ///
  1191   /// \relates LemonWriter
  1192   template <typename _Graph>
  1193   class NodeWriter : public LemonWriter::SectionWriter {
  1194     typedef LemonWriter::SectionWriter Parent;
  1195     typedef _Graph Graph;
  1196     typedef typename Graph::Node Node;
  1197   public:
  1198     
  1199     /// \brief Constructor.
  1200     ///
  1201     /// Constructor for NodeWriter. It creates the NodeWriter and
  1202     /// attach it into the given LemonWriter. The given \c _LabelWriter
  1203     /// will write the nodes' label what can be a nodeset writer.
  1204     template <typename _LabelWriter>
  1205     NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
  1206 	       const std::string& _name = std::string()) 
  1207       : Parent(_writer), name(_name) {
  1208       checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
  1209       labelWriter.reset(new _writer_bits::LabelWriter<Node, _LabelWriter>
  1210                         (_labelWriter));
  1211     }
  1212 
  1213 
  1214     /// \brief Destructor.
  1215     ///
  1216     /// Destructor for NodeWriter.
  1217     virtual ~NodeWriter() {}
  1218 
  1219   private:
  1220     NodeWriter(const NodeWriter&);
  1221     void operator=(const NodeWriter&);
  1222 
  1223   public:
  1224 
  1225     /// \brief Add a node writer command for the NodeWriter.
  1226     ///
  1227     /// Add a node writer command for the NodeWriter.
  1228     void writeNode(std::string label, const Node& item) {
  1229       writers.push_back(make_pair(label, &item));
  1230     }
  1231 
  1232   protected:
  1233 
  1234     /// \brief The header of the section.
  1235     ///
  1236     /// It gives back the header of the section.
  1237     virtual std::string header() {
  1238       return "@nodes " + name;
  1239     }
  1240 
  1241     /// \brief  Writer function of the section.
  1242     ///
  1243     /// Write the content of the section.
  1244     virtual void write(std::ostream& os) {
  1245       if (!labelWriter->isLabelWriter()) {
  1246 	throw DataFormatError("Cannot find nodeset or label map");
  1247       }
  1248       for (int i = 0; i < int(writers.size()); ++i) {
  1249 	os << writers[i].first << ' ';
  1250 	labelWriter->write(os, *(writers[i].second));
  1251 	os << std::endl;
  1252       }
  1253     }
  1254 
  1255     /// \brief Gives back true when the section should be written.
  1256     ///
  1257     /// Gives back true when the section should be written.
  1258     virtual bool valid() { return !writers.empty(); }
  1259     
  1260   private:
  1261 
  1262     std::string name;
  1263 
  1264     typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
  1265     NodeWriters writers;
  1266     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
  1267   };
  1268 
  1269   /// \ingroup section_io
  1270   /// \brief SectionWriter for writing named edges.
  1271   ///
  1272   /// The edges section's header line is \c \@edges \c edges_name, but the
  1273   /// \c edges_name may be empty.
  1274   ///
  1275   /// Each line in the section contains the name of the edge and 
  1276   /// then the edge label. 
  1277   ///
  1278   /// \relates LemonWriter
  1279   template <typename _Graph>
  1280   class EdgeWriter : public LemonWriter::SectionWriter {
  1281     typedef LemonWriter::SectionWriter Parent;
  1282     typedef _Graph Graph;
  1283     typedef typename Graph::Edge Edge;
  1284   public:
  1285     
  1286     /// \brief Constructor.
  1287     ///
  1288     /// Constructor for EdgeWriter. It creates the EdgeWriter and
  1289     /// attach it into the given LemonWriter. The given \c _LabelWriter
  1290     /// will write the edges' label what can be a edgeset writer.
  1291     template <typename _LabelWriter>
  1292     EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
  1293 	       const std::string& _name = std::string()) 
  1294       : Parent(_writer), name(_name) {
  1295       checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
  1296       labelWriter.reset(new _writer_bits::LabelWriter<Edge, _LabelWriter>(_labelWriter));
  1297     }
  1298 
  1299     /// \brief Destructor.
  1300     ///
  1301     /// Destructor for EdgeWriter.
  1302     virtual ~EdgeWriter() {}
  1303   private:
  1304     EdgeWriter(const EdgeWriter&);
  1305     void operator=(const EdgeWriter&);
  1306 
  1307   public:
  1308 
  1309     /// \brief Add an edge writer command for the EdgeWriter.
  1310     ///
  1311     /// Add an edge writer command for the EdgeWriter.
  1312     void writeEdge(std::string label, const Edge& item) {
  1313       writers.push_back(make_pair(label, &item));
  1314     }
  1315 
  1316   protected:
  1317 
  1318     /// \brief The header of the section.
  1319     ///
  1320     /// It gives back the header of the section.
  1321     virtual std::string header() {
  1322       return "@edges " + name;
  1323     }
  1324 
  1325     /// \brief  Writer function of the section.
  1326     ///
  1327     /// Write the content of the section.
  1328     virtual void write(std::ostream& os) {
  1329       if (!labelWriter->isLabelWriter()) {
  1330 	throw DataFormatError("Cannot find edgeset or label map");
  1331       }
  1332       for (int i = 0; i < int(writers.size()); ++i) {
  1333 	os << writers[i].first << ' ';
  1334 	labelWriter->write(os, *(writers[i].second));
  1335 	os << std::endl;
  1336       }
  1337     }
  1338 
  1339     /// \brief Gives back true when the section should be written.
  1340     ///
  1341     /// Gives back true when the section should be written.
  1342     virtual bool valid() { return !writers.empty(); }
  1343     
  1344   private:
  1345 
  1346     std::string name;
  1347 
  1348     typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
  1349     EdgeWriters writers;
  1350 
  1351     std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
  1352   };
  1353 
  1354 
  1355   /// \ingroup section_io
  1356   /// \brief SectionWriter for writing named undirected edges.
  1357   ///
  1358   /// The undirected edges section's header line is \c \@uedges 
  1359   /// \c uedges_name, but the \c uedges_name may be empty.
  1360   ///
  1361   /// Each line in the section contains the name of the undirected edge and 
  1362   /// then the undirected edge label. 
  1363   ///
  1364   /// \relates LemonWriter
  1365   template <typename _Graph>
  1366   class UEdgeWriter : public LemonWriter::SectionWriter {
  1367     typedef LemonWriter::SectionWriter Parent;
  1368     typedef _Graph Graph;
  1369     typedef typename Graph::Node Node;
  1370     typedef typename Graph::Edge Edge;
  1371     typedef typename Graph::UEdge UEdge;
  1372   public:
  1373     
  1374     /// \brief Constructor.
  1375     ///
  1376     /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
  1377     /// attach it into the given LemonWriter. The given \c _LabelWriter
  1378     /// will write the undirected edges' label what can be an undirected 
  1379     /// edgeset writer.
  1380     template <typename _LabelWriter>
  1381     UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
  1382 	       const std::string& _name = std::string()) 
  1383       : Parent(_writer), name(_name) {
  1384       checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
  1385       checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
  1386       uEdgeLabelWriter.reset(new _writer_bits::
  1387 			      LabelWriter<UEdge, _LabelWriter>(_labelWriter));
  1388       edgeLabelWriter.reset(new _writer_bits::
  1389 			 LabelWriter<Edge, _LabelWriter>(_labelWriter));
  1390     }
  1391 
  1392     /// \brief Destructor.
  1393     ///
  1394     /// Destructor for UEdgeWriter.
  1395     virtual ~UEdgeWriter() {}
  1396   private:
  1397     UEdgeWriter(const UEdgeWriter&);
  1398     void operator=(const UEdgeWriter&);
  1399 
  1400   public:
  1401 
  1402     /// \brief Add an edge writer command for the UEdgeWriter.
  1403     ///
  1404     /// Add an edge writer command for the UEdgeWriter.
  1405     void writeEdge(std::string label, const Edge& item) {
  1406       edgeWriters.push_back(make_pair(label, &item));
  1407     }
  1408 
  1409     /// \brief Add an undirected edge writer command for the UEdgeWriter.
  1410     ///
  1411     /// Add an undirected edge writer command for the UEdgeWriter.
  1412     void writeUEdge(std::string label, const UEdge& item) {
  1413       uEdgeWriters.push_back(make_pair(label, &item));
  1414     }
  1415 
  1416   protected:
  1417 
  1418     /// \brief The header of the section.
  1419     ///
  1420     /// It gives back the header of the section.
  1421     virtual std::string header() {
  1422       return "@uedges " + name;
  1423     }
  1424 
  1425     /// \brief  Writer function of the section.
  1426     ///
  1427     /// Write the content of the section.
  1428     virtual void write(std::ostream& os) {
  1429       if (!edgeLabelWriter->isLabelWriter()) {
  1430 	throw DataFormatError("Cannot find undirected edgeset or label map");
  1431       }
  1432       if (!uEdgeLabelWriter->isLabelWriter()) {
  1433 	throw DataFormatError("Cannot find undirected edgeset or label map");
  1434       }
  1435       for (int i = 0; i < int(uEdgeWriters.size()); ++i) {
  1436 	os << uEdgeWriters[i].first << ' ';
  1437 	uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
  1438 	os << std::endl;
  1439       }
  1440       for (int i = 0; i < int(edgeWriters.size()); ++i) {
  1441 	os << edgeWriters[i].first << ' ';
  1442 	edgeLabelWriter->write(os, *(edgeWriters[i].second));
  1443 	os << std::endl;
  1444       }
  1445     }
  1446 
  1447     /// \brief Gives back true when the section should be written.
  1448     ///
  1449     /// Gives back true when the section should be written.
  1450     virtual bool valid() { 
  1451       return !uEdgeWriters.empty() || !edgeWriters.empty(); 
  1452     }
  1453     
  1454   private:
  1455 
  1456     std::string name;
  1457 
  1458     typedef std::vector<std::pair<std::string, 
  1459 				  const UEdge*> > UEdgeWriters;
  1460     UEdgeWriters uEdgeWriters;
  1461     std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
  1462 
  1463     typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
  1464     EdgeWriters edgeWriters;
  1465     std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
  1466 
  1467   };
  1468 
  1469   /// \ingroup section_io
  1470   /// \brief SectionWriter for writing extra node maps.
  1471   ///
  1472   /// The lemon format can store maps in the nodeset. This class let
  1473   /// you make distinict section to store maps. The main purpose of
  1474   /// this class is a logical separation of some maps. The other
  1475   /// useful application could be to store paths in node maps.
  1476   ///
  1477   /// The first line of the section contains the names of the maps
  1478   /// separated with white spaces. Each next line describes an item
  1479   /// in the itemset, and contains in the first column the label of
  1480   /// the item and then the mapped values for each map.
  1481   ///
  1482   /// \relates LemonWriter
  1483   template <typename _Graph, typename _Traits = DefaultWriterTraits>
  1484   class NodeMapWriter : public LemonWriter::SectionWriter {
  1485     typedef LemonWriter::SectionWriter Parent;
  1486   public:
  1487 
  1488     typedef _Graph Graph;
  1489     typedef _Traits Traits;
  1490     typedef typename Graph::Node Node;
  1491 
  1492     /// \brief Constructor.
  1493     ///
  1494     /// Constructor for NodeMapWriter. It creates the NodeMapWriter and
  1495     /// attach it into the given LemonWriter. If the the
  1496     /// \c _forceSort is true then the writer will write the edges
  1497     /// sorted by the labels.
  1498     template <typename _LabelWriter>
  1499     NodeMapWriter(LemonWriter& _writer, const Graph& _graph,
  1500 		 const _LabelWriter& _labelWriter,
  1501 		 const std::string& _name = std::string(),
  1502 		 bool _forceSort = true) 
  1503       : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) {
  1504       checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
  1505       labelWriter.reset(new _writer_bits::LabelWriter<Node, 
  1506 			_LabelWriter>(_labelWriter));
  1507     }
  1508 
  1509     /// \brief Destructor.
  1510     ///
  1511     /// Destructor for NodeMapWriter.
  1512     virtual ~NodeMapWriter() {
  1513       typename MapWriters::iterator it;
  1514       for (it = writers.begin(); it != writers.end(); ++it) {
  1515 	delete it->second;
  1516       }
  1517     }
  1518 
  1519   private:
  1520     NodeMapWriter(const NodeMapWriter&);
  1521     void operator=(const NodeMapWriter&);
  1522   
  1523   public:
  1524 
  1525     /// \brief Add a new node map writer command for the writer.
  1526     ///
  1527     /// Add a new node map writer command for the writer.
  1528     template <typename Map>
  1529     NodeMapWriter& writeNodeMap(std::string label, const Map& map) {
  1530       return writeNodeMap<typename Traits::
  1531 	template Writer<typename Map::Value>, Map>(label, map);
  1532     }
  1533 
  1534     /// \brief Add a new node map writer command for the writer.
  1535     ///
  1536     /// Add a new node map writer command for the writer.
  1537     template <typename ItemWriter, typename Map>
  1538     NodeMapWriter& writeNodeMap(std::string label, const Map& map, 
  1539 			   const ItemWriter& iw = ItemWriter()) {
  1540       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
  1541       checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
  1542       writers.push_back(
  1543 	make_pair(label, new _writer_bits::
  1544 		  MapWriter<Node, Map, ItemWriter>(map, iw)));
  1545       return *this;
  1546     }
  1547 
  1548   protected:
  1549 
  1550     /// \brief The header of the section.
  1551     ///
  1552     /// It gives back the header of the section.
  1553     virtual std::string header() {
  1554       return "@nodemaps " + name;
  1555     }
  1556 
  1557     /// \brief  Writer function of the section.
  1558     ///
  1559     /// Write the content of the section.
  1560     virtual void write(std::ostream& os) {
  1561       std::vector<Node> nodes;
  1562       for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
  1563         nodes.push_back(it);
  1564       }
  1565       if (forceSort) {
  1566 	labelWriter->sort(nodes);
  1567       }
  1568       os << '\t';
  1569       for (int i = 0; i < int(writers.size()); ++i) {
  1570 	os << writers[i].first << '\t';
  1571       }
  1572       os << std::endl;
  1573       for (typename std::vector<Node>::iterator it = nodes.begin();
  1574            it != nodes.end(); ++it) {
  1575 
  1576 	labelWriter->write(os, *it); os << '\t';
  1577 	for (int i = 0; i < int(writers.size()); ++i) {
  1578 	  writers[i].second->write(os, *it);
  1579 	  os << '\t';
  1580 	}
  1581 	os << std::endl;
  1582       }
  1583     }
  1584 
  1585 
  1586   private:
  1587 
  1588     typedef std::vector<std::pair<std::string, _writer_bits::
  1589 				  MapWriterBase<Node>*> > MapWriters;
  1590     MapWriters writers;
  1591 
  1592     _writer_bits::MapWriterBase<Node>* labelMap;
  1593 
  1594     const Graph& graph;   
  1595     std::string name;
  1596     bool forceSort;
  1597 
  1598     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
  1599   };
  1600 
  1601   /// \ingroup section_io
  1602   /// \brief SectionWriter for writing extra edge maps.
  1603   ///
  1604   /// The lemon format can store maps in the edgeset. This class let
  1605   /// you make distinict section to store maps. The main purpose of
  1606   /// this class is a logical separation of some maps. The other
  1607   /// useful application could be to store paths in edge maps.
  1608   ///
  1609   /// The first line of the section contains the names of the maps
  1610   /// separated with white spaces. Each next line describes an item
  1611   /// in the itemset, and contains in the first column the label of
  1612   /// the item and then the mapped values for each map.
  1613   ///
  1614   /// \relates LemonWriter
  1615   template <typename _Graph, typename _Traits = DefaultWriterTraits>
  1616   class EdgeMapWriter : public LemonWriter::SectionWriter {
  1617     typedef LemonWriter::SectionWriter Parent;
  1618   public:
  1619 
  1620     typedef _Graph Graph;
  1621     typedef _Traits Traits;
  1622     typedef typename Graph::Edge Edge;
  1623 
  1624     /// \brief Constructor.
  1625     ///
  1626     /// Constructor for EdgeMapWriter. It creates the EdgeMapWriter and
  1627     /// attach it into the given LemonWriter. If the the
  1628     /// \c _forceSort is true then the writer will write the edges
  1629     /// sorted by the labels.
  1630     template <typename _LabelWriter>
  1631     EdgeMapWriter(LemonWriter& _writer, const Graph& _graph,
  1632 		 const _LabelWriter& _labelWriter,
  1633 		 const std::string& _name = std::string(),
  1634 		 bool _forceSort = true) 
  1635       : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) {
  1636       checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
  1637       labelWriter.reset(new _writer_bits::LabelWriter<Edge, 
  1638 			_LabelWriter>(_labelWriter));
  1639     }
  1640 
  1641     /// \brief Destructor.
  1642     ///
  1643     /// Destructor for EdgeMapWriter.
  1644     virtual ~EdgeMapWriter() {
  1645       typename MapWriters::iterator it;
  1646       for (it = writers.begin(); it != writers.end(); ++it) {
  1647 	delete it->second;
  1648       }
  1649     }
  1650 
  1651   private:
  1652     EdgeMapWriter(const EdgeMapWriter&);
  1653     void operator=(const EdgeMapWriter&);
  1654   
  1655   public:
  1656 
  1657     /// \brief Add a new edge map writer command for the writer.
  1658     ///
  1659     /// Add a new edge map writer command for the writer.
  1660     template <typename Map>
  1661     EdgeMapWriter& writeEdgeMap(std::string label, const Map& map) {
  1662       return writeEdgeMap<typename Traits::
  1663 	template Writer<typename Map::Value>, Map>(label, map);
  1664     }
  1665 
  1666     /// \brief Add a new edge map writer command for the writer.
  1667     ///
  1668     /// Add a new edge map writer command for the writer.
  1669     template <typename ItemWriter, typename Map>
  1670     EdgeMapWriter& writeEdgeMap(std::string label, const Map& map, 
  1671 				const ItemWriter& iw = ItemWriter()) {
  1672       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
  1673       checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
  1674       writers.push_back(
  1675 	make_pair(label, new _writer_bits::
  1676 		  MapWriter<Edge, Map, ItemWriter>(map, iw)));
  1677       return *this;
  1678     }
  1679 
  1680   protected:
  1681 
  1682     /// \brief The header of the section.
  1683     ///
  1684     /// It gives back the header of the section.
  1685     virtual std::string header() {
  1686       return "@edgemaps " + name;
  1687     }
  1688 
  1689     /// \brief  Writer function of the section.
  1690     ///
  1691     /// Write the content of the section.
  1692     virtual void write(std::ostream& os) {
  1693       std::vector<Edge> edges;
  1694       for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
  1695         edges.push_back(it);
  1696       }
  1697       if (forceSort) {
  1698 	labelWriter->sort(edges);
  1699       }
  1700       os << '\t';
  1701       for (int i = 0; i < int(writers.size()); ++i) {
  1702 	os << writers[i].first << '\t';
  1703       }
  1704       os << std::endl;
  1705       for (typename std::vector<Edge>::iterator it = edges.begin();
  1706            it != edges.end(); ++it) {
  1707 
  1708 	labelWriter->write(os, *it); os << '\t';
  1709 	for (int i = 0; i < int(writers.size()); ++i) {
  1710 	  writers[i].second->write(os, *it);
  1711 	  os << '\t';
  1712 	}
  1713 	os << std::endl;
  1714       }
  1715     }
  1716 
  1717 
  1718   private:
  1719 
  1720     typedef std::vector<std::pair<std::string, _writer_bits::
  1721 				  MapWriterBase<Edge>*> > MapWriters;
  1722     MapWriters writers;
  1723 
  1724     _writer_bits::MapWriterBase<Edge>* labelMap;
  1725 
  1726     const Graph& graph;   
  1727     std::string name;
  1728     bool forceSort;
  1729 
  1730     std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
  1731   };
  1732 
  1733   /// \ingroup section_io
  1734   /// \brief SectionWriter for writing extra undirected edge maps.
  1735   ///
  1736   /// The lemon format can store maps in the uedgeset. This class let
  1737   /// you make distinict section to store maps. The main purpose of
  1738   /// this class is a logical separation of some maps. The other
  1739   /// useful application could be to store paths in undirected edge
  1740   /// maps.
  1741   ///
  1742   /// The first line of the section contains the names of the maps
  1743   /// separated with white spaces. Each next line describes an item
  1744   /// in the itemset, and contains in the first column the label of
  1745   /// the item and then the mapped values for each map.
  1746   ///
  1747   /// \relates LemonWriter
  1748   template <typename _Graph, typename _Traits = DefaultWriterTraits>
  1749   class UEdgeMapWriter : public LemonWriter::SectionWriter {
  1750     typedef LemonWriter::SectionWriter Parent;
  1751   public:
  1752 
  1753     typedef _Graph Graph;
  1754     typedef _Traits Traits;
  1755     typedef typename Graph::UEdge UEdge;
  1756     typedef typename Graph::Edge Edge;
  1757 
  1758     /// \brief Constructor.
  1759     ///
  1760     /// Constructor for UEdgeMapWriter. It creates the UEdgeMapWriter and
  1761     /// attach it into the given LemonWriter. If the the
  1762     /// \c _forceSort is true then the writer will write the uedges
  1763     /// sorted by the labels.
  1764     template <typename _LabelWriter>
  1765     UEdgeMapWriter(LemonWriter& _writer, const Graph& _graph,
  1766 		 const _LabelWriter& _labelWriter,
  1767 		 const std::string& _name = std::string(),
  1768 		 bool _forceSort = true) 
  1769       : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) {
  1770       checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
  1771       labelWriter.reset(new _writer_bits::LabelWriter<UEdge, 
  1772 			    _LabelWriter>(_labelWriter));
  1773     }
  1774 
  1775     /// \brief Destructor.
  1776     ///
  1777     /// Destructor for UEdgeMapWriter.
  1778     virtual ~UEdgeMapWriter() {
  1779       typename MapWriters::iterator it;
  1780       for (it = writers.begin(); it != writers.end(); ++it) {
  1781 	delete it->second;
  1782       }
  1783     }
  1784 
  1785   private:
  1786     UEdgeMapWriter(const UEdgeMapWriter&);
  1787     void operator=(const UEdgeMapWriter&);
  1788   
  1789   public:
  1790 
  1791     /// \brief Add a new undirected edge map writer command for the writer.
  1792     ///
  1793     /// Add a new undirected edge map writer command for the writer.
  1794     template <typename Map>
  1795     UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map) {
  1796       return writeUEdgeMap<typename Traits::
  1797 	template Writer<typename Map::Value>, Map>(label, map);
  1798     }
  1799 
  1800     /// \brief Add a new undirected edge map writer command for the writer.
  1801     ///
  1802     /// Add a new undirected edge map writer command for the writer.
  1803     template <typename ItemWriter, typename Map>
  1804     UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map, 
  1805 			   const ItemWriter& iw = ItemWriter()) {
  1806       checkConcept<concepts::ReadMap<UEdge, typename Map::Value>, Map>();
  1807       checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
  1808       writers.push_back(
  1809 	make_pair(label, new _writer_bits::
  1810 		  MapWriter<UEdge, Map, ItemWriter>(map, iw)));
  1811       return *this;
  1812     }
  1813 
  1814     /// \brief Add a new directed edge map writer command for the writer.
  1815     ///
  1816     /// Add a new directed map writer command for the writer.
  1817     template <typename Map>
  1818     UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map) {
  1819       return writeEdgeMap<typename Traits::
  1820 	template Writer<typename Map::Value>, Map>(label, map);
  1821     }
  1822 
  1823     /// \brief Add a new directed map writer command for the writer.
  1824     ///
  1825     /// Add a new directed map writer command for the writer.
  1826     template <typename ItemWriter, typename Map>
  1827     UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map, 
  1828                                  const ItemWriter& iw = ItemWriter()) {
  1829       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
  1830       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
  1831       writeUEdgeMap("+" + label, 
  1832                     _writer_bits::forwardComposeMap(graph, map), iw);
  1833       writeUEdgeMap("-" + label, 
  1834                     _writer_bits::backwardComposeMap(graph, map), iw);
  1835       return *this;
  1836     }
  1837 
  1838   protected:
  1839 
  1840     /// \brief The header of the section.
  1841     ///
  1842     /// It gives back the header of the section.
  1843     virtual std::string header() {
  1844       return "@uedgemaps " + name;
  1845     }
  1846 
  1847     /// \brief  Writer function of the section.
  1848     ///
  1849     /// Write the content of the section.
  1850     virtual void write(std::ostream& os) {
  1851       std::vector<UEdge> uedges;
  1852       for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
  1853         uedges.push_back(it);
  1854       }
  1855       if (forceSort) {
  1856 	labelWriter->sort(uedges);
  1857       }
  1858       os << '\t';
  1859       for (int i = 0; i < int(writers.size()); ++i) {
  1860 	os << writers[i].first << '\t';
  1861       }
  1862       os << std::endl;
  1863       for (typename std::vector<UEdge>::iterator it = uedges.begin();
  1864            it != uedges.end(); ++it) {
  1865 
  1866 	labelWriter->write(os, *it); os << '\t';
  1867 	for (int i = 0; i < int(writers.size()); ++i) {
  1868 	  writers[i].second->write(os, *it);
  1869 	  os << '\t';
  1870 	}
  1871 	os << std::endl;
  1872       }
  1873     }
  1874 
  1875 
  1876   private:
  1877 
  1878     typedef std::vector<std::pair<std::string, _writer_bits::
  1879 				  MapWriterBase<UEdge>*> > MapWriters;
  1880     MapWriters writers;
  1881 
  1882     _writer_bits::MapWriterBase<UEdge>* labelMap;
  1883 
  1884     const Graph& graph;   
  1885     std::string name;
  1886     bool forceSort;
  1887 
  1888     std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > labelWriter;
  1889   };
  1890 
  1891 
  1892   /// \ingroup section_io
  1893   /// \brief SectionWriter for attributes.
  1894   ///
  1895   /// The lemon format can store multiple attribute set. Each set has
  1896   /// the header line \c \@attributes \c attributes_name, but the 
  1897   /// attributeset_name may be empty.
  1898   ///
  1899   /// The attributeset section contains several lines. Each of them starts
  1900   /// with the name of attribute and then the value.
  1901   ///
  1902   /// \relates LemonWriter
  1903   template <typename _Traits = DefaultWriterTraits>
  1904   class AttributeWriter : public LemonWriter::SectionWriter {
  1905     typedef LemonWriter::SectionWriter Parent;
  1906     typedef _Traits Traits; 
  1907   public:
  1908     /// \brief Constructor.
  1909     ///
  1910     /// Constructor for AttributeWriter. It creates the AttributeWriter and
  1911     /// attach it into the given LemonWriter.
  1912     AttributeWriter(LemonWriter& _writer, 
  1913 		    const std::string& _name = std::string()) 
  1914       : Parent(_writer), name(_name) {}
  1915 
  1916     /// \brief Destructor.
  1917     ///
  1918     /// Destructor for AttributeWriter.
  1919     virtual ~AttributeWriter() {
  1920       typename Writers::iterator it;
  1921       for (it = writers.begin(); it != writers.end(); ++it) {
  1922 	delete it->second;
  1923       }
  1924     }
  1925 
  1926   private:
  1927     AttributeWriter(const AttributeWriter&);
  1928     void operator=(AttributeWriter&);
  1929 
  1930   public:
  1931     /// \brief Add an attribute writer command for the writer.
  1932     ///
  1933     /// Add an attribute writer command for the writer.
  1934     template <typename Value>
  1935     AttributeWriter& writeAttribute(std::string label, 
  1936 				    const Value& value) {
  1937       return 
  1938 	writeAttribute<typename Traits::template Writer<Value> >(label, value);
  1939     }
  1940 
  1941     /// \brief Add an attribute writer command for the writer.
  1942     ///
  1943     /// Add an attribute writer command for the writer.
  1944     template <typename ItemWriter, typename Value>
  1945     AttributeWriter& writeAttribute(std::string label, const Value& value,
  1946 				    const ItemWriter& iw = ItemWriter()) {
  1947       checkConcept<_writer_bits::ItemWriter<Value>, ItemWriter>();
  1948       writers.push_back(make_pair(label, new _writer_bits::
  1949 				  ValueWriter<Value, ItemWriter>(value, iw)));
  1950       return *this;
  1951     }
  1952 
  1953   protected:
  1954 
  1955     /// \brief The header of section.
  1956     ///
  1957     /// It gives back the header of the section.
  1958     std::string header() {
  1959       return "@attributes " + name;
  1960     }
  1961 
  1962     /// \brief  Writer function of the section.
  1963     ///
  1964     /// Write the content of the section.
  1965     void write(std::ostream& os) {
  1966       typename Writers::iterator it;
  1967       for (it = writers.begin(); it != writers.end(); ++it) {
  1968 	os << it->first << ' ';
  1969 	it->second->write(os);
  1970 	os << std::endl;
  1971       }
  1972     }    
  1973 
  1974     /// \brief Gives back true when the section should be written.
  1975     ///
  1976     /// Gives back true when the section should be written.
  1977     virtual bool valid() { return !writers.empty(); }
  1978 
  1979   private:
  1980     std::string name;
  1981 
  1982     typedef std::vector<std::pair<std::string, 
  1983 				  _writer_bits::ValueWriterBase*> > Writers;
  1984     Writers writers;  
  1985   };
  1986 
  1987 
  1988 }
  1989 #endif