Index: src/lemon/Makefile.am
===================================================================
--- src/lemon/Makefile.am	(revision 1408)
+++ src/lemon/Makefile.am	(revision 1409)
@@ -54,4 +54,5 @@
 	utility.h \
 	lemon_reader.h \
+	lemon_writer.h \
 	graph_reader.h \
 	graph_writer.h \
@@ -67,5 +68,6 @@
 	bits/erasable_graph_extender.h \
 	bits/undir_graph_extender.h \
-	bits/item_reader.h
+	bits/item_reader.h \
+	bits/item_writer.h
 
 noinst_HEADERS = \
Index: src/lemon/bits/item_writer.h
===================================================================
--- src/lemon/bits/item_writer.h	(revision 1409)
+++ src/lemon/bits/item_writer.h	(revision 1409)
@@ -0,0 +1,214 @@
+/* -*- C++ -*-
+ * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+/// \ingroup io_group
+/// \file
+/// \brief Item writer bits for lemon output.
+
+#ifndef LEMON_BITS_ITEM_WRITER_H
+#define LEMON_BITS_ITEM_WRITER_H
+
+#include <iostream>
+#include <string>
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <set>
+
+namespace lemon {
+  
+  template <typename Value>
+  class DefaultWriter;
+
+  /// \ingroup io_group
+  /// \brief Writer class for quoted strings.
+  ///
+  /// Writer class for quoted strings. It can process the escape
+  /// sequences in the string.
+  /// \author Balazs Dezso
+  class QuotedStringWriter {
+  public:
+    typedef std::string Value;
+
+    /// \brief Constructor for the writer.
+    ///
+    /// Constructor for the writer. If the given parameter is true
+    /// the writer creates escape sequences from special characters.
+    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
+
+    /// \brief Writes a quoted string to the given stream.
+    ///
+    /// Writes a quoted string to the given stream.
+    void write(std::ostream& os, const std::string& value) {
+      os << "\"";
+      if (escaped) {
+	std::ostringstream ls;
+	for (int i = 0; i < (int)value.size(); ++i) {
+	  writeEscape(ls, value[i]);
+	}
+	os << ls.str();
+      } else {
+	os << value;
+      }
+      os << "\"";
+    }
+
+  private:
+    
+    static void writeEscape(std::ostream& os, char c) {
+      switch (c) {
+      case '\\':
+	os << "\\\\";
+	return;
+      case '\"':
+	os << "\\\"";
+	return;
+      case '\'':
+	os << "\\\'";
+	return;
+      case '\?':
+	os << "\\\?";
+	return;
+      case '\a':
+	os << "\\a";
+	return;
+      case '\b':
+	os << "\\b";
+	return;
+      case '\f':
+	os << "\\f";
+	return;
+      case '\r':
+	os << "\\r";
+	return;
+      case '\n':
+	os << "\\n";
+	return;
+      case '\t':
+	os << "\\t";
+	return;
+      case '\v':
+	os << "\\v";
+	return;
+      default:
+	if (c < 0x20) {
+	  os << '\\' << std::oct << (int)c;
+	} else {
+	  os << c;
+	}
+	return;
+      }     
+    }
+  private:
+    bool escaped;
+  };
+
+  /// \ingroup io_group
+  ///
+  /// \brief Writer for standard containers.
+  ///
+  /// Writer for each iterable standard containers. The representation
+  /// of the container is the values enumerated between an open and a
+  /// close parse. 
+  ///
+  /// \author Balazs Dezso
+  template <
+    typename _Container, 
+    typename _ItemWriter = DefaultWriter<typename _Container::value_type> 
+  >
+  class IterableWriter {
+  public:
+    typedef _Container Value;
+    typedef _ItemWriter ItemWriter;
+
+  private:
+
+    ItemWriter item_writer;
+
+  public:
+
+    /// \brief Writes the values of the container to the given stream.
+    ///
+    /// Writes the values of the container to the given stream.
+    void write(std::ostream& os, const Value& value) const {
+      typename Value::const_iterator it;
+      os << '(';
+      for (it = value.begin(); it != value.end(); ++it) {
+	item_writer.write(os, *it);
+	os << ' ';
+      }
+      os << ')';
+    }
+
+  };
+
+  /// \ingroup io_group
+  /// 
+  /// \brief The default item writer template class.
+  ///
+  /// The default item writer template class. If some section writer
+  /// needs to write a value to the stream it will give the default way for it.
+  ///
+  /// \author Balazs Dezso
+  template <typename _Value>
+  class DefaultWriter {
+  public:
+    /// The value type.
+    typedef _Value Value;
+    /// \brief Writes the value to the given stream.
+    ///
+    /// Writes the value to the given stream.
+    void write(std::ostream& os, const Value& value) const {
+      os << value;
+    }
+  };
+
+  template <typename Item>
+  class DefaultWriter<std::vector<Item> > 
+    : public IterableWriter<std::vector<Item> > {};
+
+  template <typename Item>
+  class DefaultWriter<std::deque<Item> > 
+    : public IterableWriter<std::deque<Item> > {};
+
+  template <typename Item>
+  class DefaultWriter<std::list<Item> > 
+    : public IterableWriter<std::list<Item> > {};
+  
+  template <typename Item>
+  class DefaultWriter<std::set<Item> > 
+    : public IterableWriter<std::set<Item> > {};
+
+  template <typename Item>
+  class DefaultWriter<std::multiset<Item> > 
+    : public IterableWriter<std::multiset<Item> > {};
+
+  /// \brief Standard WriterTraits for the section writers.
+  ///
+  /// Standard WriterTraits for the section writers.
+  /// It defines standard writing method for all type of value. 
+  /// \author Balazs Dezso
+  struct DefaultWriterTraits {
+
+    template <typename _Value>
+    struct Writer : DefaultWriter<_Value> {};
+
+  };
+
+}
+
+#endif
Index: src/lemon/graph_writer.h
===================================================================
--- src/lemon/graph_writer.h	(revision 1402)
+++ src/lemon/graph_writer.h	(revision 1409)
@@ -23,16 +23,7 @@
 
 #include <iostream>
-#include <sstream>
-
-#include <map>
-#include <vector>
-
-#include <memory>
-
-#include <lemon/graph_utils.h>
-
-#include <lemon/invalid.h>
+
 #include <lemon/error.h>
-
+#include <lemon/lemon_writer.h>
 
 namespace lemon {
@@ -41,126 +32,4 @@
   /// @{
 
-  /// \brief Standard WriterTraits for the GraphWriter class.
-  ///
-  /// Standard WriterTraits for the GraphWriter class.
-  /// It defines standard writing method for all type of value. 
-  /// \author Balazs Dezso
-  struct DefaultWriterTraits {
-
-    /// \brief Template class for writing an value.
-    ///
-    /// Template class for writing an value.
-    /// \author Balazs Dezso
-    template <typename _Value>
-    struct Writer {
-      /// The value type.
-      typedef _Value Value;
-
-      /// \brief Writes a value to the given stream.
-      ///
-      /// Writes a value to the given stream.
-      void write(std::ostream& os, const Value& value) {
-	os << value << '\t';
-      }
-    };
-
-    /// \brief Returns wheter this name is an ID map name.
-    ///
-    /// Returns wheter this name is an ID map name.
-    static bool idMapName(const std::string& name) {
-      return name == "id";
-    }
-
-  };
-
-
-  /// \brief Writer class for quoted strings.
-  ///
-  /// Writer class for quoted strings. It can process the escape
-  /// sequences in the string.
-  /// \author Balazs Dezso
-  class QuotedStringWriter {
-  public:
-    typedef std::string Value;
-
-    /// \brief Constructor for the writer.
-    ///
-    /// Constructor for the writer. If the given parameter is true
-    /// the writer creates escape sequences from special characters.
-    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
-
-    /// \brief Writes a quoted string to the given stream.
-    ///
-    /// Writes a quoted string to the given stream.
-    void write(std::ostream& os, const std::string& value) {
-      os << "\"";
-      if (escaped) {
-	std::ostringstream ls;
-	for (int i = 0; i < (int)value.size(); ++i) {
-	  writeEscape(ls, value[i]);
-	}
-	os << ls.str();
-      } else {
-	os << value;
-      }
-      os << "\"";
-    }
-
-  private:
-    
-    static void writeEscape(std::ostream& os, char c) {
-      switch (c) {
-      case '\\':
-	os << "\\\\";
-	return;
-      case '\"':
-	os << "\\\"";
-	return;
-      case '\'':
-	os << "\\\'";
-	return;
-      case '\?':
-	os << "\\\?";
-	return;
-      case '\a':
-	os << "\\a";
-	return;
-      case '\b':
-	os << "\\b";
-	return;
-      case '\f':
-	os << "\\f";
-	return;
-      case '\r':
-	os << "\\r";
-	return;
-      case '\n':
-	os << "\\n";
-	return;
-      case '\t':
-	os << "\\t";
-	return;
-      case '\v':
-	os << "\\v";
-	return;
-      default:
-	if (c < 0x20) {
-	  os << '\\' << std::oct << (int)c;
-	} else {
-	  os << c;
-	}
-	return;
-      }     
-    }
-  private:
-    bool escaped;
-  };
-
-  class GUIWriter {
-  public:
-    virtual void write(std::ostream& os) = 0;
-  };
-
-  
   /// \brief The graph writer class.
   ///
@@ -232,18 +101,46 @@
     typedef _Graph Graph;
     typedef typename Graph::Node Node;
-    typedef typename Graph::NodeIt NodeIt;
     typedef typename Graph::Edge Edge;
-    typedef typename Graph::EdgeIt EdgeIt;
 
     typedef _WriterTraits WriterTraits;
- 
+
     /// \brief Construct a new GraphWriter.
     ///
-    /// Construct a new GraphWriter. It writes from the given map,
-    /// it constructs the given map and it use the given writer as the
-    /// default skipper.
+    /// Construct a new GraphWriter. It writes the given graph
+    /// to the given stream.
     GraphWriter(std::ostream& _os, const Graph& _graph) 
-      : gui_writer(0), os(_os), graph(_graph){}
-
+      : writer(new LemonWriter(_os)), own_writer(true), 
+	graph(_graph), 
+	nodeset_writer(*writer, graph, std::string()),
+	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
+	node_writer(*writer, nodeset_writer, std::string()),
+	edge_writer(*writer, edgeset_writer, std::string()),
+	attribute_writer(*writer, std::string()) {}
+
+    /// \brief Construct a new GraphWriter.
+    ///
+    /// Construct a new GraphWriter. It writes into the given graph
+    /// to the given file.
+    GraphWriter(const std::string& _filename, const Graph& _graph) 
+      : writer(new LemonWriter(_filename)), own_writer(true), 
+	graph(_graph),
+	nodeset_writer(*writer, graph, std::string(), skipper),
+	edgeset_writer(*writer, graph, nodeset_writer, std::string(), skipper),
+	node_writer(*writer, nodeset_writer, std::string()),
+	edge_writer(*writer, edgeset_writer, std::string()),
+	attribute_writer(*writer, std::string()) {}
+
+    /// \brief Construct a new GraphWriter.
+    ///
+    /// Construct a new GraphWriter. It writes into the given graph
+    /// to given LemonReader.
+    GraphWriter(LemonWriter& _writer, const Graph& _graph)
+      : writer(_writer), own_writer(false), 
+	graph(_graph),
+	nodeset_writer(*writer, graph, std::string()),
+	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
+	node_writer(*writer, nodeset_writer, std::string()),
+	edge_writer(*writer, edgeset_writer, std::string()),
+	attribute_writer(*writer, std::string()) {}
 
     /// \brief Destruct the graph writer.
@@ -251,17 +148,7 @@
     /// Destruct the graph writer.
     ~GraphWriter() {
-      for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
-	   it != node_map_writers.end(); ++it) {
-	delete it->second;
-      }
-
-      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
-	   it != edge_map_writers.end(); ++it) {
-	delete it->second;
-      }
-
-    }
-
-    // Node map rules
+      if (own_writer) 
+	delete writer;
+    }
 
     /// \brief Add a new node map writer command for the writer.
@@ -270,6 +157,6 @@
     template <typename Map>
     GraphWriter& writeNodeMap(std::string name, const Map& map) {
-      return writeNodeMap<typename WriterTraits::template Writer<
-	typename Map::Value>, Map>(name, map);
+      nodeset_writer.writeMap(name, map);
+      return *this;
     }
 
@@ -279,11 +166,9 @@
     template <typename Writer, typename Map>
     GraphWriter& writeNodeMap(std::string name, const Map& map, 
-			      const Writer& writer = Writer()) {
-      node_map_writers.push_back(
-        make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
-      return *this;
-    }
-
-    // Edge map rules
+			     const Writer& writer = Writer()) {
+      nodeset_writer.writeMap(name, map, writer);
+      return *this;
+    }
+
 
     /// \brief Add a new edge map writer command for the writer.
@@ -292,6 +177,6 @@
     template <typename Map>
     GraphWriter& writeEdgeMap(std::string name, const Map& map) { 
-      return writeEdgeMap<typename WriterTraits::template Writer<
-        typename Map::Value>, Map>(name, map);
+      edgeset_writer.writeMap(name, map);
+      return *this;
     }
 
@@ -301,8 +186,7 @@
     /// Add a new edge map writer command for the writer.
     template <typename Writer, typename Map>
-    GraphWriter& writeEdgeMap(std::string name, 
-			    const Map& map, const Writer& writer = Writer()) {
-      edge_map_writers.push_back(make_pair(name, 
-	new MapWriter<Edge, Map, Writer>(map, writer)));
+    GraphWriter& writeEdgeMap(std::string name, const Map& map,
+			     const Writer& writer = Writer()) {
+      edgeset_writer.writeMap(name, map, writer);
       return *this;
     }
@@ -312,5 +196,5 @@
     /// Add a new labeled node writer for the writer.
     GraphWriter& writeNode(std::string name, const Node& node) {
-      node_writers.push_back(make_pair(name, node));
+      node_writer.writeNode(name, node);
       return *this;
     }
@@ -320,10 +204,34 @@
     /// Add a new labeled edge writer for the writer.
     GraphWriter& writeEdge(std::string name, const Edge& edge) {
-      edge_writers.push_back(make_pair(name, edge));
-      return *this;
-    }
-
-    GraphWriter& writeGUI(const GUIWriter& writer) {
-      gui_writer = &writer;
+      edge_writer.writeEdge(name, edge);
+    }
+
+    /// \brief Add a new attribute writer command.
+    ///
+    ///  Add a new attribute writer command.
+    template <typename Value>
+    GraphWriter& writeAttribute(std::string name, const Value& value) {
+      attribute_writer.writeAttribute(name, value);
+      return *this;
+    }
+    
+    /// \brief Add a new attribute writer command.
+    ///
+    ///  Add a new attribute writer command.
+    template <typename Writer, typename Value>
+    GraphWriter& writeAttribute(std::string name, const Value& value, 
+			       const Writer& writer) {
+      attribute_writer.writeAttribute<Writer>(name, value, writer);
+      return *this;
+    }
+
+    /// \brief Conversion operator to LemonWriter.
+    ///
+    /// Conversion operator to LemonWriter. It make possible
+    /// to access the encapsulated \e LemonWriter, this way
+    /// you can attach to this writer new instances of 
+    /// \e LemonWriter::SectionWriter.
+    operator LemonWriter&() {
+      return *writer;
     }
 
@@ -331,146 +239,24 @@
     ///
     /// Executes the writer commands.
-    void run() {   
-      WriterBase<Node>* nodeWriter = 0;
-      WriterBase<Edge>* edgeWriter = 0;
-      writeNodeSet(nodeWriter);
-      writeEdgeSet(nodeWriter, edgeWriter);
-      writeNodes(nodeWriter);
-      writeEdges(edgeWriter);
-      writeGUI();
-      os << "@end" << std::endl;
+    void run() {
+      writer->run();
     }
 
   private:
 
-    template <class _Item>
-    class WriterBase {
-    public:
-      typedef _Item Item;
-      virtual void write(std::ostream&, const Item&) = 0;
-    };
-
-    template <class _Item, typename _Map, typename _Writer>
-    class MapWriter : public WriterBase<_Item> {
-    public:
-      typedef _Map Map;
-      typedef _Writer Writer;
-      typedef typename Writer::Value Value;
-      typedef _Item Item;
-      
-      const Map& map;
-      Writer writer;
-
-      MapWriter(const Map& _map, const Writer& _writer) 
-	: map(_map), writer(_writer) {}
-
-
-      virtual void write(std::ostream& os, const Item& item) {
-	writer.write(os, map[item]);
-      }
-
-    };
-
-    void writeNodeSet(WriterBase<Node>* & nodeWriter) {
-      if (node_map_writers.size() == 0) return;
-      os << "@nodeset" << std::endl;
-      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
-	const std::string& id = node_map_writers[i].first;
-	os << id << '\t';
-	if (WriterTraits::idMapName(id) && nodeWriter == 0) {
-	  nodeWriter = node_map_writers[i].second;
-	}
-      } 
-      os << std::endl;
-      for (NodeIt it(graph); it != INVALID; ++it) {
-	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
-	  node_map_writers[i].second->write(os, it);
-	}
-	os << std::endl;
-      }
-
-    }
-
-    void writeEdgeSet(WriterBase<Node>* nodeWriter, 
-		      WriterBase<Edge>* & edgeWriter) {
-      if (edge_map_writers.size() == 0) return;
-      if (nodeWriter == 0) {
-	throw DataFormatError("Cannot find node id map");
-      }
-      os << "@edgeset" << std::endl;
-      os << "\t\t";
-      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
-	const std::string& id = edge_map_writers[i].first;
-	os << id << '\t';
-	if (WriterTraits::idMapName(id) && edgeWriter == 0) {
-	  edgeWriter = edge_map_writers[i].second;
-	}
-      } 
-      os << std::endl;
-      for (EdgeIt it(graph); it != INVALID; ++it) {
-	nodeWriter->write(os, graph.source(it));
-	nodeWriter->write(os, graph.target(it));
-	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
-	  edge_map_writers[i].second->write(os, it);
-	}
-	os << std::endl;
-      }
-    }
-
-    void writeNodes(WriterBase<Node>* nodeWriter) {
-      if (node_writers.size() == 0) return;
-      if (nodeWriter == 0) {
-	throw DataFormatError("Cannot find node id map");
-      }
-      os << "@nodes" << std::endl;
-      for (int i = 0; i < (int)node_writers.size(); ++i) {
-	os << node_writers[i].first << '\t';
-	nodeWriter->write(os, node_writers[i].second);
-	os << std::endl;
-      } 
-    }
-
-    void writeEdges(WriterBase<Edge>* edgeWriter) {
-      if (edge_writers.size() == 0) return;
-      if (edgeWriter == 0) {
-	throw DataFormatError("Cannot find node id map");
-      }
-      os << "@edges" << std::endl;
-      for (int i = 0; i < (int)edge_writers.size(); ++i) {
-	os << edge_writers[i].first << '\t';
-        edgeWriter->write(os, edge_writers[i].second);
-	os << std::endl;
-      } 
-    }
+    LemonWriter* writer;
+    bool own_writer;
+
+    const Graph& graph;
+
+    NodeSetWriter<Graph, WriterTraits> nodeset_writer;
+    EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
+
+    NodeWriter<Graph> node_writer;
+    EdgeWriter<Graph> edge_writer;
     
-    void writeGUI() {      
-      if (gui_writer) {
-	os << "@gui" << std::endl;
-	gui_writer->write(os);
-      }
-    }
-
-
-
-    typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
-      NodeMapWriters;
-    NodeMapWriters node_map_writers;
-
-    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
-      EdgeMapWriters;
-    EdgeMapWriters edge_map_writers;
-
-    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
-    NodeWriters node_writers;
-
-    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
-    EdgeWriters edge_writers;
-
-    GUIWriter* gui_writer;
-
-    std::ostream& os;
-    const Graph& graph;
-
+    AttributeWriter<WriterTraits> attribute_writer;
   };
+
 
   /// \brief Write a graph to the output.
Index: src/lemon/lemon_reader.h
===================================================================
--- src/lemon/lemon_reader.h	(revision 1408)
+++ src/lemon/lemon_reader.h	(revision 1409)
@@ -31,14 +31,39 @@
 
 #include <lemon/error.h>
-#include "item_reader.h"
+#include <lemon/bits/item_reader.h>
 
 
 namespace lemon {
 
-  /// \addtogroup io_group
-  /// @{
-
+  /// \ingroup io_group
   /// \brief Lemon Format reader class.
   /// 
+  /// The Lemon Format contains several sections. We do not want to
+  /// determine what sections are in a lemon file we give only a framework
+  /// to read a section oriented format.
+  ///
+  /// In the Lemon Format each section starts with a line contains a \c \@
+  /// character on the first not white space position. This line is the
+  /// header line of the section. Each next lines belong to this section
+  /// while it does not starts with \c \@ character. This line can start a 
+  /// new section or if it can close the file with the \c \@end line.
+  /// The file format ignore the empty lines and it may contain comments
+  /// started with a \c # character to the end of the line. 
+  ///
+  /// The framework provides an abstract LemonReader::SectionReader class
+  /// what defines the interface of a SectionReader. The SectionReader
+  /// has the \c header() member function what get a header line string and
+  /// decides if it want to process the next section. Several SectionReaders
+  /// can be attached to an LemonReader and the first attached what can
+  /// process the section will be used. Its \c read() member will called
+  /// with a stream contains the section. From this stream the empty lines
+  /// and comments are filtered out.
+  ///
+  /// \relates GraphReader
+  /// \relates NodeSetReader
+  /// \relates EdgeSetReader
+  /// \relates NodesReader
+  /// \relates EdgesReader
+  /// \relates AttributeReader
   class LemonReader {
   private:
@@ -186,16 +211,45 @@
   public:
 
+    /// \brief Abstract base class for reading a section.
+    ///
+    /// This class has an \c header() member function what get a 
+    /// header line string and decides if it want to process the next 
+    /// section. Several SectionReaders can be attached to an LemonReader 
+    /// and the first attached what can process the section will be used. 
+    /// Its \c read() member will called with a stream contains the section. 
+    /// From this stream the empty lines and comments are filtered out.
     class SectionReader {
-    public:
-      /// \e
+      friend class LemonReader;
+    protected:
+      /// \brief Constructor for SectionReader.
+      ///
+      /// Constructor for SectionReader. It attach this reader to
+      /// the given LemonReader.
+      SectionReader(LemonReader& reader) {
+	reader.attach(*this);
+      }
+
+      /// \brief Gives back true when the SectionReader can process 
+      /// the section with the given header line.
+      ///
+      /// It gives back true when the SectionReader can process
+      /// the section with the given header line.
       virtual bool header(const std::string& line) = 0;
-      /// \e
+
+      /// \brief Reader function of the section.
+      ///
+      /// It reads the content of the section.
       virtual void read(std::istream& is) = 0;
     };
 
-    /// \e
+    /// \brief Constructor for LemonReader.
+    ///
+    /// Constructor for LemonReader which reads from the given stream.
     LemonReader(std::istream& _is) 
       : is(&_is), own_is(false) {}
 
+    /// \brief Constructor for LemonReader.
+    ///
+    /// Constructor for LemonReader which reads from the given file.
     LemonReader(const std::string& filename) 
       : is(0), own_is(true) {
@@ -203,5 +257,7 @@
     }
 
-
+    /// \brief Desctructor for LemonReader.
+    ///
+    /// Desctructor for LemonReader.
     ~LemonReader() {
       if (own_is) {
@@ -214,21 +270,12 @@
     void operator=(const LemonReader&);
 
-  public:
-    
-    /// \e
     void attach(SectionReader& reader) {
       readers.push_back(&reader);
     }
 
-    /// \e
-    void detach(SectionReader& reader) {
-      std::vector<SectionReader*>::iterator it = 
-	std::find(readers.begin(), readers.end(), &reader);
-      if (it != readers.end()) {
-	readers.erase(it);
-      }
-    }
-
-    /// \e
+  public:
+    /// \brief Executes the LemonReader.
+    /// 
+    /// It executes the LemonReader.
     void run() {
       int line_num = 0;
@@ -265,8 +312,18 @@
   };
 
-
-  /// \e
+  /// \brief Helper class for implementing the common SectionReaders.
+  ///
+  /// Helper class for implementing the common SectionReaders.
   class CommonSectionReaderBase : public LemonReader::SectionReader {
+    typedef LemonReader::SectionReader Parent;
   protected:
+    
+    /// \brief Constructor for CommonSectionReaderBase.
+    ///
+    /// Constructor for CommonSectionReaderBase. It attach this reader to
+    /// the given LemonReader.
+    CommonSectionReaderBase(LemonReader& _reader) 
+      : Parent(_reader) {}
+
     template <typename _Item>
     class ReaderBase;
@@ -434,23 +491,23 @@
 
     template <typename _Item>
-    class ResolverReaderBase {
+    class IdReaderBase {
     public:
       typedef _Item Item;
-      virtual Item resolve(std::istream& is) const = 0;
+      virtual Item read(std::istream& is) const = 0;
     };
 
-    template <typename _Item, typename _Resolver>
-    class ResolverReader : public ResolverReaderBase<_Item> {
+    template <typename _Item, typename _BoxedIdReader>
+    class IdReader : public IdReaderBase<_Item> {
     public:
       typedef _Item Item;
-      typedef _Resolver Resolver;
-
-      const Resolver& resolver;
-
-      ResolverReader(const Resolver& _resolver) 
-	: resolver(_resolver) {}
-
-      virtual Item resolve(std::istream& is) const {
-	return resolver.resolve(is);
+      typedef _BoxedIdReader BoxedIdReader;
+      
+      const BoxedIdReader& boxedIdReader;
+
+      IdReader(const BoxedIdReader& _boxedIdReader) 
+	: boxedIdReader(_boxedIdReader) {}
+
+      virtual Item read(std::istream& is) const {
+	return boxedIdReader.readId(is);
       }
     };
@@ -480,5 +537,21 @@
   };
 
-
+  /// \ingroup io_group
+  /// \brief SectionReader for reading a graph's nodeset.
+  ///
+  /// The lemon format can store multiple graph nodesets with several maps.
+  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
+  /// \c nodeset_id may be empty.
+  ///
+  /// The first line of the section contains the names of the maps separated
+  /// with white spaces. Each next lines describes a node in the nodeset, and
+  /// contains the mapped values for each map.
+  ///
+  /// If the nodeset contains an \c "id" named map then it will be regarded
+  /// as id map. This map should contain only unique values and when the 
+  /// \c readId() member will read a value from the given stream it will
+  /// give back that node which is mapped to this value.
+  ///
+  /// \relates LemonReader
   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   class NodeSetReader : public CommonSectionReaderBase {
@@ -491,11 +564,19 @@
     typedef typename Traits::Skipper DefaultSkipper;
 
+    /// \brief Constructor.
+    ///
+    /// Constructor for NodeSetReader. It creates the NodeSetReader and
+    /// attach it into the given LemonReader. The nodeset reader will
+    /// add the readed nodes to the given Graph. The reader will read
+    /// the section when the \c section_id and the \c _id are the same. 
     NodeSetReader(LemonReader& _reader, Graph& _graph, 
 		  const std::string& _id = std::string(),
-		  const DefaultSkipper& _defreader = DefaultSkipper()) 
-      : graph(_graph), id(_id), skipper(_defreader) {
-      _reader.attach(*this);
-    } 
-
+		  const DefaultSkipper& _skipper = DefaultSkipper()) 
+      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
+
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for NodeSetReader.
     virtual ~NodeSetReader() {
       for (typename MapReaders::iterator it = readers.begin(); 
@@ -551,5 +632,11 @@
     }
 
-    /// \e
+  protected:
+
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
+    ///
+    /// It gives back true when the header line starts with \c @nodeset,
+    /// and the header line's id and the nodeset's id are the same.
     virtual bool header(const std::string& line) {
       std::istringstream ls(line);
@@ -560,5 +647,7 @@
     }
 
-    /// \e
+    /// \brief Reader function of the section.
+    ///
+    /// It reads the content of the section.
     virtual void read(std::istream& is) {
       std::vector<ReaderBase<Item>* > index;
@@ -588,9 +677,19 @@
     }
 
-    bool isResolver() const {
+  public:
+
+    /// \brief Returns true if the nodeset can give back the node by its id.
+    ///
+    /// Returns true if the nodeset can give back the node by its id.
+    /// It is possible only if an "id" named map was read.
+    bool isIdReader() const {
       return inverter.get() != 0;
     }
 
-    typename Graph::Node resolve(std::istream& is) const {
+    /// \brief Gives back the node by its id.
+    ///
+    /// It reads an id from the stream and gives back which node belongs to
+    /// it. It is possible only if there was read an "id" named map.
+    typename Graph::Node readId(std::istream& is) const {
       return inverter->read(is);
     } 
@@ -608,7 +707,25 @@
   };
 
-
- 
-  /// \e
+  /// \ingroup io_group
+  /// \brief SectionReader for reading a graph's edgeset.
+  ///
+  /// The lemon format can store multiple graph edgesets with several maps.
+  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
+  /// \c edgeset_id may be empty.
+  ///
+  /// The first line of the section contains the names of the maps separated
+  /// with white spaces. Each next lines describes a node in the nodeset. The
+  /// line contains the two nodes' id and the mapped values for each map.
+  ///
+  /// If the edgeset contains an \c "id" named map then it will be regarded
+  /// as id map. This map should contain only unique values and when the 
+  /// \c readId() member will read a value from the given stream it will
+  /// give back that edge which is mapped to this value.
+  ///
+  /// The edgeset reader needs a node id reader to identify which nodes
+  /// have to be connected. If a NodeSetReader reads an "id" named map,
+  /// it will be able to resolve the nodes by ids.
+  ///
+  /// \relates LemonReader
   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   class EdgeSetReader : public CommonSectionReaderBase {
@@ -621,15 +738,24 @@
     typedef typename Traits::Skipper DefaultSkipper;
 
-    template <typename Resolver>
+    /// \brief Constructor.
+    ///
+    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
+    /// attach it into the given LemonReader. The edgeset reader will
+    /// add the readed edges to the given Graph. It will use the given
+    /// node id reader to read the source and target nodes of the edges.
+    /// The reader will read the section only if the \c _id and the 
+    /// \c edgset_id are the same. 
+    template <typename NodeIdReader>
     EdgeSetReader(LemonReader& _reader, Graph& _graph, 
-		  const Resolver& _nodeResolver, 
+		  const NodeIdReader& _nodeIdReader, 
 		  const std::string& _id = std::string(),
-		  const DefaultSkipper& _defreader = DefaultSkipper()) 
-      : graph(_graph), id(_id), skipper(_defreader),
-      nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
-		   (_nodeResolver)) {
-      _reader.attach(*this);
-    } 
-
+		  const DefaultSkipper& _skipper = DefaultSkipper()) 
+      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
+	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
+		     (_nodeIdReader)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for EdgeSetReader.
     virtual ~EdgeSetReader() {
       for (typename MapReaders::iterator it = readers.begin(); 
@@ -645,7 +771,7 @@
   public:
 
-    /// \brief Add a new node map reader command for the reader.
-    ///
-    /// Add a new node map reader command for the reader.
+    /// \brief Add a new edge map reader command for the reader.
+    ///
+    /// Add a new edge map reader command for the reader.
     template <typename Map>
     EdgeSetReader& readMap(std::string name, Map& map) {
@@ -654,7 +780,7 @@
     }
 
-    /// \brief Add a new node map reader command for the reader.
-    ///
-    /// Add a new node map reader command for the reader.
+    /// \brief Add a new edge map reader command for the reader.
+    ///
+    /// Add a new edge map reader command for the reader.
     template <typename Reader, typename Map>
     EdgeSetReader& readMap(std::string name, Map& map, 
@@ -670,7 +796,7 @@
     }
 
-    /// \brief Add a new node map skipper command for the reader.
-    ///
-    /// Add a new node map skipper command for the reader.
+    /// \brief Add a new edge map skipper command for the reader.
+    ///
+    /// Add a new edge map skipper command for the reader.
     template <typename Reader>
     EdgeSetReader& skipMap(std::string name, 
@@ -685,5 +811,11 @@
     }
 
-    /// \e
+  protected:
+
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
+    ///
+    /// It gives back true when the header line starts with \c @edgeset,
+    /// and the header line's id and the edgeset's id are the same.
     virtual bool header(const std::string& line) {
       std::istringstream ls(line);
@@ -694,5 +826,7 @@
     }
 
-    /// \e
+    /// \brief Reader function of the section.
+    ///
+    /// It reads the content of the section.
     virtual void read(std::istream& is) {
       std::vector<ReaderBase<Item>* > index;
@@ -715,6 +849,6 @@
       while (getline(is, line)) {	
 	std::istringstream ls(line);
-	typename Graph::Node from = nodeResolver->resolve(ls);
-	typename Graph::Node to = nodeResolver->resolve(ls);
+	typename Graph::Node from = nodeIdReader->read(ls);
+	typename Graph::Node to = nodeIdReader->read(ls);
 	typename Graph::Edge edge = graph.addEdge(from, to);
 	for (int i = 0; i < (int)index.size(); ++i) {
@@ -724,9 +858,19 @@
     }
 
-    bool isResolver() const {
+  public:
+
+    /// \brief Returns true if the edgeset can give back the edge by its id.
+    ///
+    /// Returns true if the edgeset can give back the edge by its id.
+    /// It is possible only if an "id" named map was read.
+    bool isIdReader() const {
       return inverter.get() != 0;
     }
 
-    typename Graph::Edge resolve(std::istream& is) {
+    /// \brief Gives back the edge by its id.
+    ///
+    /// It reads an id from the stream and gives back which edge belongs to
+    /// it. It is possible only if there was read an "id" named map.
+    typename Graph::Edge readId(std::istream& is) const {
       return inverter->read(is);
     } 
@@ -742,9 +886,201 @@
 
     std::auto_ptr<InverterBase<Item> > inverter;
-    std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
+    std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
   };
 
-
-  /// \e
+  /// \ingroup io_group
+  /// \brief SectionReader for reading labeled nodes.
+  ///
+  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
+  /// \c nodes_id may be empty.
+  ///
+  /// Each line in the section contains the name of the node 
+  /// and then the node id. 
+  ///
+  /// \relates LemonReader
+  template <typename _Graph>
+  class NodeReader : public CommonSectionReaderBase {
+    typedef CommonSectionReaderBase Parent;
+    typedef _Graph Graph;
+    typedef typename Graph::Node Item;
+  public:
+    
+    /// \brief Constructor.
+    ///
+    /// Constructor for NodeReader. It creates the NodeReader and
+    /// attach it into the given LemonReader. It will use the given
+    /// node id reader to give back the nodes. The reader will read the 
+    /// section only if the \c _id and the \c nodes_id are the same. 
+    template <typename _IdReader>
+    NodeReader(LemonReader& _reader, const _IdReader& _idReader, 
+	       const std::string& _id = std::string()) 
+      : Parent(_reader), id(_id), 
+	idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for NodeReader.
+    virtual ~NodeReader() {}
+
+  private:
+    NodeReader(const NodeReader&);
+    void operator=(const NodeReader&);
+
+  public:
+
+    /// \brief Add a node reader command for the NodeReader.
+    ///
+    /// Add a node reader command for the NodeReader.
+    void readNode(const std::string& name, Item& item) {
+      if (readers.find(name) != readers.end()) {
+	ErrorMessage msg;
+	msg << "Multiple read rule for node: " << name;
+	throw IOParameterError(msg.message());
+      }
+      readers.insert(make_pair(name, &item));
+    }
+
+  protected:
+
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
+    ///
+    /// It gives back true when the header line start with \c @nodes,
+    /// and the header line's id and the reader's id are the same.
+    virtual bool header(const std::string& line) {
+      std::istringstream ls(line);
+      std::string command;
+      std::string name;
+      ls >> command >> name;
+      return command == "@nodes" && name == id;
+    }
+
+    /// \brief Reader function of the section.
+    ///
+    /// It reads the content of the section.
+    virtual void read(std::istream& is) {
+      std::string line;
+      while (getline(is, line)) {
+	std::istringstream ls(line);
+	std::string id;
+	ls >> id;
+	typename ItemReaders::iterator it = readers.find(id);
+	if (it != readers.end()) {
+	  *(it->second) = idReader->read(ls); 
+	}	
+      }
+    }
+    
+  private:
+
+    std::string id;
+
+    typedef std::map<std::string, Item*> ItemReaders;
+    ItemReaders readers;
+    std::auto_ptr<IdReaderBase<Item> > idReader;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionReader for reading labeled edges.
+  ///
+  /// The edges section's header line is \c \@edges \c edges_id, but the
+  /// \c edges_id may be empty.
+  ///
+  /// Each line in the section contains the name of the edge 
+  /// and then the edge id. 
+  ///
+  /// \relates LemonReader
+  template <typename _Graph>
+  class EdgeReader : public CommonSectionReaderBase {
+    typedef CommonSectionReaderBase Parent;
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Item;
+  public:
+    
+    /// \brief Constructor.
+    ///
+    /// Constructor for EdgeReader. It creates the EdgeReader and
+    /// attach it into the given LemonReader. It will use the given
+    /// edge id reader to give back the edges. The reader will read the 
+    /// section only if the \c _id and the \c nodes_id are the same. 
+    template <typename _IdReader>
+    EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
+	       const std::string& _id = std::string()) 
+      : Parent(_reader), id(_id), 
+	idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for EdgeReader.
+    virtual ~EdgeReader() {}
+  private:
+    EdgeReader(const EdgeReader&);
+    void operator=(const EdgeReader&);
+
+  public:
+
+    /// \brief Add an edge reader command for the EdgeReader.
+    ///
+    /// Add an edge reader command for the EdgeReader.
+    void readEdge(const std::string& name, Item& item) {
+      if (readers.find(name) != readers.end()) {
+	ErrorMessage msg;
+	msg << "Multiple read rule for edge: " << name;
+	throw IOParameterError(msg.message());
+      }
+      readers.insert(make_pair(name, &item));
+    }
+
+  protected:
+
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
+    ///
+    /// It gives back true when the header line start with \c @edges,
+    /// and the header line's id and the reader's id are the same.
+    virtual bool header(const std::string& line) {
+      std::istringstream ls(line);
+      std::string command;
+      std::string name;
+      ls >> command >> name;
+      return command == "@edges" && name == id;
+    }
+
+    /// \brief Reader function of the section.
+    ///
+    /// It reads the content of the section.
+    virtual void read(std::istream& is) {
+      std::string line;
+      while (getline(is, line)) {
+	std::istringstream ls(line);
+	std::string id;
+	ls >> id;
+	typename ItemReaders::iterator it = readers.find(id);
+	if (it != readers.end()) {
+	  *(it->second) = idReader->read(ls); 
+	}	
+      }
+    }
+    
+  private:
+
+    std::string id;
+
+    typedef std::map<std::string, Item*> ItemReaders;
+    ItemReaders readers;
+    std::auto_ptr<IdReaderBase<Item> > idReader;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionReader for attributes.
+  ///
+  /// The lemon format can store multiple attribute set. Each set has
+  /// the header line \c \@attributes \c attributeset_id, but the 
+  /// attributeset_id may be empty.
+  ///
+  /// The attributeset section contains several lines. Each of them starts
+  /// with an attribute and then a the value for the id.
+  ///
+  /// \relates LemonReader
   template <typename _Traits = DefaultReaderTraits>
   class AttributeReader : public CommonSectionReaderBase {
@@ -752,11 +1088,16 @@
     typedef _Traits Traits; 
   public:
-    /// \e
+    /// \brief Constructor.
+    ///
+    /// Constructor for AttributeReader. It creates the AttributeReader and
+    /// attach it into the given LemonReader. The reader process a section
+    /// only if the \c section_id and the \c _id are the same.
     AttributeReader(LemonReader& _reader, 
-		    const std::string& _id = std::string()) : id(_id) {
-      _reader.attach(*this);
-    }
-
-    /// \e
+		    const std::string& _id = std::string()) 
+      : Parent(_reader), id(_id) {}
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for AttributeReader.
     virtual ~AttributeReader() {
       for (typename Readers::iterator it = readers.begin(); 
@@ -771,5 +1112,7 @@
 
   public:
-    /// \e
+    /// \brief Add an attribute reader command for the reader.
+    ///
+    /// Add an attribute reader command for the reader.
     template <typename Value>
     AttributeReader& readAttribute(const std::string& id, Value& value) {
@@ -778,5 +1121,7 @@
     }
 
-    /// \e
+    /// \brief Add an attribute reader command for the reader.
+    ///
+    /// Add an attribute reader command for the reader.
     template <typename Reader, typename Value>
     AttributeReader& readAttribute(const std::string& name, Value& value,
@@ -792,5 +1137,11 @@
     }
 
-    /// \e
+  protected:
+
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
+    ///
+    /// It gives back true when the header line start with \c @attributes,
+    /// and the header line's id and the attributeset's id are the same.
     bool header(const std::string& line) {
       std::istringstream ls(line);
@@ -801,5 +1152,7 @@
     }
 
-    /// \e
+    /// \brief Reader function of the section.
+    ///
+    /// It reads the content of the section.
     void read(std::istream& is) {
       std::string line;
@@ -819,159 +1172,8 @@
 
     typedef std::map<std::string, ValueReaderBase*> Readers;
-    Readers readers;
-  
+    Readers readers;  
   };
 
-  template <typename _Graph>
-  class NodeReader : public CommonSectionReaderBase {
-    typedef CommonSectionReaderBase Parent;
-    typedef _Graph Graph;
-    typedef typename Graph::Node Item;
-  public:
-    
-    template <typename Resolver>
-    NodeReader(LemonReader& _reader, const Resolver& _resolver, 
-	       const std::string& _id = std::string()) 
-      : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
-		     (_resolver)) {
-      _reader.attach(*this);
-    } 
-
-    virtual ~NodeReader() {}
-
-  private:
-    NodeReader(const NodeReader&);
-    void operator=(const NodeReader&);
-
-  public:
-
-    void readNode(const std::string& name, Item& item) {
-      if (readers.find(name) != readers.end()) {
-	ErrorMessage msg;
-	msg << "Multiple read rule for node: " << name;
-	throw IOParameterError(msg.message());
-      }
-      readers.insert(make_pair(name, &item));
-    }
-
-    virtual bool header(const std::string& line) {
-      std::istringstream ls(line);
-      std::string command;
-      std::string name;
-      ls >> command >> name;
-      return command == "@nodes" && name == id;
-    }
-
-    virtual void read(std::istream& is) {
-      std::string line;
-      while (getline(is, line)) {
-	std::istringstream ls(line);
-	std::string id;
-	ls >> id;
-	typename ItemReaders::iterator it = readers.find(id);
-	if (it != readers.end()) {
-	  *(it->second) = resolver->resolve(ls); 
-	}	
-      }
-    }
-    
-  private:
-
-    std::string id;
-
-    typedef std::map<std::string, Item*> ItemReaders;
-    ItemReaders readers;
-    std::auto_ptr<ResolverReaderBase<Item> > resolver;
-  };
-
-  template <typename _Graph>
-  class EdgeReader : public CommonSectionReaderBase {
-    typedef CommonSectionReaderBase Parent;
-    typedef _Graph Graph;
-    typedef typename Graph::Edge Item;
-  public:
-    
-    template <typename Resolver>
-    EdgeReader(LemonReader& _reader, const Resolver& _resolver, 
-	       const std::string& _id = std::string()) 
-      : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
-		     (_resolver)) {
-      _reader.attach(*this);
-    } 
-
-    virtual ~EdgeReader() {}
-  private:
-    EdgeReader(const EdgeReader&);
-    void operator=(const EdgeReader&);
-
-  public:
-
-    void readEdge(const std::string& name, Item& item) {
-      if (readers.find(name) != readers.end()) {
-	ErrorMessage msg;
-	msg << "Multiple read rule for edge: " << name;
-	throw IOParameterError(msg.message());
-      }
-      readers.insert(make_pair(name, &item));
-    }
-
-
-    virtual bool header(const std::string& line) {
-      std::istringstream ls(line);
-      std::string command;
-      std::string name;
-      ls >> command >> name;
-      return command == "@nodes" && name == id;
-    }
-
-    virtual void read(std::istream& is) {
-      std::string line;
-      while (getline(is, line)) {
-	std::istringstream ls(line);
-	std::string id;
-	ls >> id;
-	typename ItemReaders::iterator it = readers.find(id);
-	if (it != readers.end()) {
-	  *(it->second) = resolver->resolve(ls); 
-	}	
-      }
-    }
-    
-  private:
-
-    std::string id;
-
-    typedef std::map<std::string, Item*> ItemReaders;
-    ItemReaders readers;
-    std::auto_ptr<ResolverReaderBase<Item> > resolver;
-  };
-
-  /// \e
-  class PrintReader : public LemonReader::SectionReader {
-    typedef LemonReader::SectionReader Parent;
-  public:
-
-    /// \e
-    PrintReader(LemonReader& reader) {
-      reader.attach(*this);
-    }
-
-    /// \e
-    bool header(const std::string& line) {
-      std::cout << "Asked header: " << line << std::endl; 
-      return true;
-    }
-
-    /// \e
-    void read(std::istream& is) {
-      std::string line;
-      while (std::getline(is, line)) {
-	std::cout << line << std::endl;
-      }
-    }
-  
-  };
-
-  /// @}
+
 }
 #endif
Index: src/lemon/lemon_writer.h
===================================================================
--- src/lemon/lemon_writer.h	(revision 1409)
+++ src/lemon/lemon_writer.h	(revision 1409)
@@ -0,0 +1,813 @@
+/* -*- C++ -*-
+ * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup io_group
+///\file
+///\brief Lemon Format writer.
+
+#ifndef LEMON_LEMON_WRITER_H
+#define LEMON_LEMON_WRITER_H
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <map>
+#include <memory>
+
+#include <lemon/error.h>
+#include <lemon/invalid.h>
+#include <lemon/bits/item_writer.h>
+
+
+namespace lemon {
+
+  /// \ingroup io_group
+  /// \brief Lemon Format writer class.
+  /// 
+  /// The Lemon Format contains several sections. We do not want to
+  /// determine what sections are in a lemon file we give only a framework
+  /// to write a section oriented format.
+  ///
+  /// In the Lemon Format each section starts with a line contains a \c \@
+  /// character on the first not white space position. This line is the
+  /// header line of the section. Each next lines belong to this section
+  /// while it does not starts with \c \@ character. This line can start a 
+  /// new section or if it can close the file with the \c \@end line.
+  /// The file format ignore the empty lines and it may contain comments
+  /// started with a \c # character to the end of the line. 
+  ///
+  /// The framework provides an abstract LemonWriter::SectionWriter class
+  /// what defines the interface of a SectionWriter. The SectionWriter
+  /// has the \c header() member function what gives back the header of the
+  /// section. After that it will be called the \c write() member which
+  /// should write the content of the section.
+  ///
+  /// \relates GraphWriter
+  /// \relates NodeSetWriter
+  /// \relates EdgeSetWriter
+  /// \relates NodesWriter
+  /// \relates EdgesWriter
+  /// \relates AttributeWriter
+  class LemonWriter {
+  public:
+
+    /// \brief Abstract base class for writing a section.
+    ///
+    /// This class has an \c header() member function what gives back
+    /// the header line of the section. The \c write() member should
+    /// write the content of the section to the stream.
+    class SectionWriter {
+      friend class LemonWriter;
+    protected:
+      /// \brief Constructor for SectionWriter.
+      ///
+      /// Constructor for SectionWriter. It attach this writer to
+      /// the given LemonWriter.
+      SectionWriter(LemonWriter& writer) {
+	writer.attach(*this);
+      }
+
+      /// \brief The header of section.
+      ///
+      /// It gives back the header of the section.
+      virtual std::string header() = 0;
+
+      /// \brief  Writer function of the section.
+      ///
+      /// Write the content of the section.
+      virtual void write(std::ostream& os) = 0;
+    };
+
+    /// \brief Constructor for LemonWriter.
+    ///
+    /// Constructor for LemonWriter which writes to the given stream.
+    LemonWriter(std::ostream& _os) 
+      : os(&_os), own_os(false) {}
+
+    /// \brief Constructor for LemonWriter.
+    ///
+    /// Constructor for LemonWriter which writes to the given file.
+    LemonWriter(const std::string& filename) 
+      : os(0), own_os(true) {
+      os = new std::ofstream(filename.c_str());
+    }
+
+    /// \brief Desctructor for LemonWriter.
+    ///
+    /// Desctructor for LemonWriter.
+    ~LemonWriter() {
+      if (own_os) {
+	delete os;
+      }
+    }
+
+  private:
+    LemonWriter(const LemonWriter&);
+    void operator=(const LemonWriter&);
+
+    void attach(SectionWriter& writer) {
+      writers.push_back(&writer);
+    }
+
+  public:
+
+    /// \brief Executes the LemonWriter.
+    /// 
+    /// It executes the LemonWriter.
+    void run() {
+      SectionWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	*os << (*it)->header() << std::endl;
+	(*it)->write(*os);
+      }
+      *os << "@end" << std::endl;
+    }
+
+
+  private:
+
+    std::ostream* os;
+    bool own_os;
+
+    typedef std::vector<SectionWriter*> SectionWriters;
+    SectionWriters writers;
+
+  };
+
+  /// \brief Helper class for implementing the common SectionWriters.
+  ///
+  /// Helper class for implementing the common SectionWriters.
+  class CommonSectionWriterBase : public LemonWriter::SectionWriter {
+    typedef LemonWriter::SectionWriter Parent;
+  protected:
+    
+    /// \brief Constructor for CommonSectionWriterBase.
+    ///
+    /// Constructor for CommonSectionWriterBase. It attach this writer to
+    /// the given LemonWriter.
+    CommonSectionWriterBase(LemonWriter& _writer) 
+      : Parent(_writer) {}
+
+    // Writers
+
+    template <typename _Item>    
+    class WriterBase {
+    public:
+      typedef _Item Item;
+
+      virtual ~WriterBase() {}
+
+      virtual void write(std::ostream& os, const Item& item) = 0;
+    };
+
+
+    template <typename _Item, typename _Map, typename _Writer>
+    class MapWriter : public WriterBase<_Item> {
+    public:
+      typedef _Map Map;
+      typedef _Writer Writer;
+      typedef typename Writer::Value Value;
+      typedef _Item Item;
+      
+      const Map& map;
+      Writer writer;
+
+      MapWriter(const Map& _map, const Writer& _writer) 
+	: map(_map), writer(_writer) {}
+
+      virtual ~MapWriter() {}
+
+      virtual void write(std::ostream& os, const Item& item) {
+	Value value = map[item];
+	writer.write(os, value);
+      }
+
+    };
+
+
+    class ValueWriterBase {
+    public:
+      virtual void write(std::ostream&) = 0;
+    };
+
+    template <typename _Value, typename _Writer>
+    class ValueWriter : public ValueWriterBase {
+    public:
+      typedef _Value Value;
+      typedef _Writer Writer;
+
+      ValueWriter(const Value& _value, const Writer& _writer)
+ 	: value(_value), writer(_writer) {}
+
+      virtual void write(std::ostream& os) {
+	writer.write(is, value);
+      }
+    private:
+      const Value& value;
+      Writer writer;
+    };
+    
+
+    template <typename _Item>
+    class IdWriterBase {
+    public:
+      typedef _Item Item;
+      virtual void write(std::ostream&, const Item&) const = 0;
+    };
+
+    template <typename _Item, typename _BoxedIdWriter>
+    class IdWriter : public IdWriterBase<_Item> {
+    public:
+      typedef _Item Item;
+      typedef _BoxedIdWriter BoxedIdWriter;
+
+      const BoxedIdWriter& idWriter;
+
+      IdWriter(const BoxedIdWriter& _idWriter) 
+	: idWriter(_idWriter) {}
+
+      virtual void write(std::ostream& os, const Item& item) const {
+	return idWriter.writeId(os, item);
+      }
+    };
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writing a graph's nodeset.
+  ///
+  /// The lemon format can store multiple graph nodesets with several maps.
+  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
+  /// \c nodeset_id may be empty.
+  ///
+  /// The first line of the section contains the names of the maps separated
+  /// with white spaces. Each next lines describes a node in the nodeset, and
+  /// contains the mapped values for each map.
+  ///
+  /// If the nodeset contains an \c "id" named map then it will be regarded
+  /// as id map. This map should contain only unique values and when the 
+  /// \c writeId() member will be called with a node it will write it's id.
+  /// Otherwise if the \c _forceIdMap constructor parameter is true then
+  /// the id map will be the id in the graph.
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph, typename _Traits = DefaultWriterTraits>
+  class NodeSetWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef _Traits Traits;
+    typedef typename Graph::Node Item;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
+    /// attach it into the given LemonWriter. If the \c _forceIdMap
+    /// parameter is true then the writer will write own id map when
+    /// the user does not give "id" named map.
+    NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
+		  const std::string& _id = std::string(), 
+		  bool _forceIdMap = true) 
+      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), 
+	graph(_graph), id(_id) {}
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for NodeSetWriter.
+    virtual ~NodeSetWriter() {
+      typename MapWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    NodeSetWriter(const NodeSetWriter&);
+    void operator=(const NodeSetWriter&);
+  
+  public:
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Map>
+    NodeSetWriter& writeMap(std::string name, const Map& map) {
+      return writeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(name, map);
+    }
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Writer, typename Map>
+    NodeSetWriter& writeMap(std::string name, const Map& map, 
+			     const Writer& writer = Writer()) {
+      writers.push_back(
+	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of the section.
+    ///
+    /// It gives back the header of the section.
+    virtual std::string header() {
+      return "@nodeset " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	if (writers[i].first == "id") {
+	  idMap = writers[i].second;
+	  forceIdMap = false;
+	  break;
+	}
+      }
+      if (forceIdMap) {
+	os << "id\t";
+      }
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << '\t';
+      }
+      os << std::endl;
+      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
+	if (forceIdMap) {
+	  os << graph.id(it) << '\t';
+	}
+	for (int i = 0; i < (int)writers.size(); ++i) {
+	  writers[i].second->write(os, it);
+	  os << '\t';
+	}
+	os << std::endl;
+      }
+    }
+
+  public:
+
+    /// \brief Returns true if the nodeset can write the ids of the nodes.
+    ///
+    /// Returns true if the nodeset can write the ids of the nodes.
+    /// It is possible only if an "id" named map was written or the 
+    /// \c _forceIdMap constructor parameter was true.
+    bool isIdWriter() const {
+      return idMap != 0 || forceIdMap;
+    }
+
+    /// \brief Write the id of the given node.
+    ///
+    /// It writes the id of the given node. If there was written an "id"
+    /// named map then it will write the map value belongs to the node.
+    /// Otherwise if the \c forceId parameter was true it will write
+    /// its id in the graph. 
+    void writeId(std::ostream& os, const Item& item) const {
+      if (forceIdMap) {
+	os << graph.id(item);
+      } else {
+	idMap->write(os, item);
+      }
+    }
+
+  private:
+
+    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
+    MapWriters writers;
+
+    WriterBase<Item>* idMap;
+    bool forceIdMap;
+   
+    const Graph& graph;   
+    std::string id;
+
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writing a graph's edgeset.
+  ///
+  /// The lemon format can store multiple graph edgesets with several maps.
+  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
+  /// \c edgeset_id may be empty.
+  ///
+  /// The first line of the section contains the names of the maps separated
+  /// with white spaces. Each next lines describes a edge in the edgeset. The
+  /// line contains the source and the target nodes' id and the mapped 
+  /// values for each map.
+  ///
+  /// If the edgeset contains an \c "id" named map then it will be regarded
+  /// as id map. This map should contain only unique values and when the 
+  /// \c writeId() member will be called with a edge it will write it's id.
+  /// Otherwise if the \c _forceIdMap constructor parameter is true then
+  /// the id map will be the id in the graph.
+  ///
+  /// The edgeset writer needs a node id writer to identify which nodes
+  /// have to be connected. If a NodeSetWriter can write the nodes' id,
+  /// it will be able to use with this class.
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph, typename _Traits = DefaultWriterTraits>
+  class EdgeSetWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef _Traits Traits;
+    typedef typename Graph::Edge Item;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
+    /// attach it into the given LemonWriter. It will write node ids by
+    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
+    /// then the writer will write own id map when the user does not give 
+    /// "id" named map.
+    template <typename NodeIdWriter>
+    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
+		  const NodeIdWriter& _nodeIdWriter, 
+		  const std::string& _id = std::string(),
+		  bool _forceIdMap = true)
+      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
+	graph(_graph), id(_id),
+	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
+		     (_nodeIdWriter)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for EdgeSetWriter.
+    virtual ~EdgeSetWriter() {
+      typename MapWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    EdgeSetWriter(const EdgeSetWriter&);
+    void operator=(const EdgeSetWriter&);
+
+  public:
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Map>
+    EdgeSetWriter& writeMap(std::string name, const Map& map) {
+      return writeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(name, map);
+    }
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Writer, typename Map>
+    EdgeSetWriter& writeMap(std::string name, const Map& map, 
+			     const Writer& writer = Writer()) {
+      writers.push_back(
+	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of the section.
+    ///
+    /// It gives back the header of the section.
+    virtual std::string header() {
+      return "@edgeset " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	if (writers[i].first == "id") {
+	  idMap = writers[i].second;
+	  forceIdMap = false;
+	  break;
+	}
+      }
+      os << "\t\t";
+      if (forceIdMap) {
+	os << "id\t";
+      }
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << '\t';
+      }
+      os << std::endl;
+      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
+	nodeIdWriter->write(os, graph.source(it));
+	os << '\t';
+	nodeIdWriter->write(os, graph.target(it));
+	os << '\t';
+	if (forceIdMap) {
+	  os << graph.id(it) << '\t';
+	}
+	for (int i = 0; i < (int)writers.size(); ++i) {
+	  writers[i].second->write(os, it);
+	  os << '\t';
+	}
+	os << std::endl;
+      }
+    }
+
+  public:
+
+    /// \brief Returns true if the edgeset can write the ids of the edges.
+    ///
+    /// Returns true if the edgeset can write the ids of the edges.
+    /// It is possible only if an "id" named map was written or the 
+    /// \c _forceIdMap constructor parameter was true.
+    bool isIdWriter() const {
+      return forceIdMap || idMap != 0;
+    }
+
+    /// \brief Write the id of the given edge.
+    ///
+    /// It writes the id of the given edge. If there was written an "id"
+    /// named map then it will write the map value belongs to the edge.
+    /// Otherwise if the \c forceId parameter was true it will write
+    /// its id in the graph. 
+    void writeId(std::ostream& os, const Item& item) const {
+      if (forceIdMap) {
+	os << graph.id(item);
+      } else {
+	idMap->write(os, item);
+      }
+    } 
+
+  private:
+
+    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
+    MapWriters writers;
+
+    WriterBase<Item>* idMap;
+    bool forceIdMap;
+   
+    const Graph& graph;   
+    std::string id;
+
+    std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writing labeled nodes.
+  ///
+  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
+  /// \c nodes_id may be empty.
+  ///
+  /// Each line in the section contains the label of the node and 
+  /// then the node id. 
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph>
+  class NodeWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+    typedef _Graph Graph;
+    typedef typename Graph::Node Item;
+  public:
+    
+    /// \brief Constructor.
+    ///
+    /// Constructor for NodeWriter. It creates the NodeWriter and
+    /// attach it into the given LemonWriter. The given \c _IdWriter
+    /// will write the nodes' id what can be a nodeset writer.
+    template <typename _IdWriter>
+    NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
+	       const std::string& _id = std::string()) 
+      : Parent(_writer), id(_id), 
+	idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for NodeWriter.
+    virtual ~NodeWriter() {}
+
+  private:
+    NodeWriter(const NodeWriter&);
+    void operator=(const NodeWriter&);
+
+  public:
+
+    /// \brief Add a node writer command for the NodeWriter.
+    ///
+    /// Add a node writer command for the NodeWriter.
+    void writeNode(const std::string& name, const Item& item) {
+      writers.push_back(make_pair(name, &item));
+    }
+
+  protected:
+
+    /// \brief Header checking function.
+    ///
+    /// It gives back true when the header line start with \c @nodes,
+    /// and the header line's id and the writer's id are the same.
+    virtual std::string header() {
+      return "@nodes " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << ' ';
+	idWriter->write(os, *(writers[i].second));
+	os << std::endl;
+      }
+    }
+    
+  private:
+
+    std::string id;
+
+    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
+    ItemWriters writers;
+    std::auto_ptr<IdWriterBase<Item> > idWriter;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writeing labeled edges.
+  ///
+  /// The edges section's header line is \c \@edges \c edges_id, but the
+  /// \c edges_id may be empty.
+  ///
+  /// Each line in the section contains the label of the edge and 
+  /// then the edge id. 
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph>
+  class EdgeWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Item;
+  public:
+    
+    /// \brief Constructor.
+    ///
+    /// Constructor for EdgeWriter. It creates the EdgeWriter and
+    /// attach it into the given LemonWriter. The given \c _IdWriter
+    /// will write the edges' id what can be a edgeset writer.
+    template <typename _IdWriter>
+    EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
+	       const std::string& _id = std::string()) 
+      : Parent(_writer), id(_id), 
+	idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for EdgeWriter.
+    virtual ~EdgeWriter() {}
+  private:
+    EdgeWriter(const EdgeWriter&);
+    void operator=(const EdgeWriter&);
+
+  public:
+
+    /// \brief Add an edge writer command for the NodeWriter.
+    ///
+    /// Add an edge writer command for the NodeWriter.
+    void writeEdge(const std::string& name, const Item& item) {
+      writers.push_back(make_pair(name, &item));
+    }
+
+  protected:
+
+    /// \brief Header checking function.
+    ///
+    /// It gives back true when the header line start with \c @nodes,
+    /// and the header line's id and the writer's id are the same.
+    virtual std::string header() {
+      return "@edges " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << ' ';
+	idWriter->write(os, *(writers[i].second));
+	os << std::endl;
+      }
+    }
+    
+  private:
+
+    std::string id;
+
+    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
+    ItemWriters writers;
+
+    std::auto_ptr<IdWriterBase<Item> > idWriter;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for attributes.
+  ///
+  /// The lemon format can store multiple attribute set. Each set has
+  /// the header line \c \@attributes \c attributeset_id, but the 
+  /// attributeset_id may be empty.
+  ///
+  /// The attributeset section contains several lines. Each of them starts
+  /// with the name of attribute and then the value.
+  ///
+  /// \relates LemonWriter
+  template <typename _Traits = DefaultWriterTraits>
+  class AttributeWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+    typedef _Traits Traits; 
+  public:
+    /// \brief Constructor.
+    ///
+    /// Constructor for AttributeWriter. It creates the AttributeWriter and
+    /// attach it into the given LemonWriter.
+    AttributeWriter(LemonWriter& _writer, 
+		    const std::string& _id = std::string()) 
+      : Parent(_writer), id(_id) {}
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for AttributeWriter.
+    virtual ~AttributeWriter() {
+      typename Writers::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    AttributeWriter(const AttributeWriter&);
+    void operator=(AttributeWriter&);
+
+  public:
+    /// \brief Add an attribute writer command for the writer.
+    ///
+    /// Add an attribute writer command for the writer.
+    template <typename Value>
+    AttributeWriter& writeAttribute(const std::string& id, 
+				    const Value& value) {
+      return 
+	writeAttribute<typename Traits::template Writer<Value> >(id, value);
+    }
+
+    /// \brief Add an attribute writer command for the writer.
+    ///
+    /// Add an attribute writer command for the writer.
+    template <typename Writer, typename Value>
+    AttributeWriter& writeAttribute(const std::string& name, 
+				    const Value& value,
+				    const Writer& writer = Writer()) {
+      writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
+      			       (value, writer)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of section.
+    ///
+    /// It gives back the header of the section.
+    std::string header() {
+      return "@attributes " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    void write(std::ostream& os) {
+      typename Writers::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	os << it->first << ' ';
+	it->second->write(os);
+	os << std::endl;
+      }
+    }    
+
+  private:
+    std::string id;
+
+    typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
+    Writers writers;  
+  };
+
+
+}
+#endif
