deba@1409: /* -*- C++ -*-
ladanyi@1435:  * lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
deba@1409:  *
alpar@1875:  * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1409:  * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1409:  *
deba@1409:  * Permission to use, modify and distribute this software is granted
deba@1409:  * provided that this copyright notice appears in all copies. For
deba@1409:  * precise terms see the accompanying LICENSE file.
deba@1409:  *
deba@1409:  * This software is provided "AS IS" with no warranty of any kind,
deba@1409:  * express or implied, and with no claim as to its suitability for any
deba@1409:  * purpose.
deba@1409:  *
deba@1409:  */
deba@1409: 
deba@1409: ///\ingroup io_group
deba@1409: ///\file
deba@1409: ///\brief Lemon Format writer.
deba@1409: 
deba@1409: #ifndef LEMON_LEMON_WRITER_H
deba@1409: #define LEMON_LEMON_WRITER_H
deba@1409: 
deba@1409: #include <iostream>
deba@1409: #include <fstream>
deba@1409: #include <string>
deba@1409: #include <vector>
deba@1409: #include <algorithm>
deba@1409: #include <map>
deba@1409: #include <memory>
deba@1409: 
deba@1409: #include <lemon/error.h>
deba@1409: #include <lemon/invalid.h>
deba@1421: #include <lemon/graph_utils.h>
deba@1409: #include <lemon/bits/item_writer.h>
deba@1421: #include <lemon/utility.h>
deba@1421: #include <lemon/maps.h>
deba@1705: #include <lemon/xy.h>
deba@1409: 
deba@1476: #include <lemon/concept_check.h>
deba@1476: #include <lemon/concept/maps.h>
deba@1476: 
deba@1409: 
deba@1409: namespace lemon {
deba@1409: 
deba@1476:   namespace _writer_bits {
deba@1476:     
deba@1476:     template <typename Item>
deba@1901:     class ItemLabelWriter {
deba@1476:     public:
deba@1476: 
deba@1901:       bool isLabelWriter() { return true; }
deba@1476: 
deba@1901:       void writeLabel(std::ostream&, const Item&) {}
deba@1476:       
deba@1901:       template <class _ItemLabelWriter>
deba@1476:       struct Constraints {
deba@1476: 	void constraints() {
deba@1901: 	  bool b = writer.isLabelWriter();
deba@1476: 	  ignore_unused_variable_warning(b);
deba@1901: 	  writer.writeLabel(os, item);
deba@1476: 	}
deba@1901: 	_ItemLabelWriter& writer;
deba@1476: 	std::ostream& os;
deba@1492: 	const Item& item;
deba@1492:       };
deba@1492: 
deba@1492:     };
deba@1492: 
deba@1492:     template <typename Item>
deba@1492:     class ItemWriter {
deba@1492:     public:
deba@1492: 
deba@1492:       void write(std::ostream&, const Item&) {}
deba@1492:       
deba@1492:       template <class _ItemWriter>
deba@1492:       struct Constraints {
deba@1492: 	void constraints() {
deba@1492: 	  writer.write(os, item);
deba@1492: 	}
deba@1492: 	_ItemWriter& writer;
deba@1492: 	std::ostream& os;
deba@1492: 	const Item& item;
deba@1476:       };
deba@1476: 
deba@1476:     };
deba@1476: 
deba@1705:     template <typename Map>
deba@1705:     struct Ref { typedef const Map& Type; };
deba@1705: 
deba@1705:     template <typename Graph, typename Map>
deba@1705:     class ForwardComposeMap {
deba@1705:     public:
klao@1909:       typedef typename Graph::UEdge Key;
deba@1705:       typedef typename Map::Value Value;
deba@1705: 
deba@1705:       ForwardComposeMap(const Graph& _graph, const Map& _map) 
deba@1705: 	: graph(_graph), map(_map) {}
deba@1705:       
deba@1705:       Value operator[](const Key& key) {
deba@1705: 	return map[graph.direct(key, false)];
deba@1705:       }
deba@1705: 
deba@1705:     private:
deba@1705:       typename Ref<Map>::Type map;
deba@1705:       const Graph& graph;
deba@1705:     };
deba@1705: 
deba@1705:     template <typename Graph, typename Map>
deba@1705:     ForwardComposeMap<Graph, Map>
deba@1705:     forwardComposeMap(const Graph& graph, const Map& map) {
deba@1705:       return ForwardComposeMap<Graph, Map>(graph, map);
deba@1705:     }
deba@1705: 
deba@1705:     template <typename Graph, typename Map>
deba@1705:     class BackwardComposeMap {
deba@1705:     public:
klao@1909:       typedef typename Graph::UEdge Key;
deba@1705:       typedef typename Map::Value Value;
deba@1705: 
deba@1705:       BackwardComposeMap(const Graph& _graph, const Map& _map) 
deba@1705: 	: graph(_graph), map(_map) {}
deba@1705:       
deba@1705:       Value operator[](const Key& key) {
deba@1705: 	return map[graph.direct(key, false)];
deba@1705:       }
deba@1705: 
deba@1705:     private:
deba@1705:       typename Ref<Map>::Type map;
deba@1705:       const Graph& graph;
deba@1705:     };
deba@1705: 
deba@1705:     template <typename Graph, typename Map>
deba@1705:     BackwardComposeMap<Graph, Map>
deba@1705:     backwardComposeMap(const Graph& graph, const Map& map) {
deba@1705:       return BackwardComposeMap<Graph, Map>(graph, map);
deba@1705:     }
deba@1705: 
deba@1705:     template <typename Graph, typename Map>
deba@1705:     struct Ref<ForwardComposeMap<Graph, Map> > { 
deba@1705:       typedef ForwardComposeMap<Graph, Map> Type;
deba@1705:     };
deba@1705: 
deba@1705:     template <typename Graph, typename Map>
deba@1705:     struct Ref<BackwardComposeMap<Graph, Map> > { 
deba@1705:       typedef BackwardComposeMap<Graph, Map> Type; 
deba@1705:     };
deba@1705: 
deba@1705:     template <typename Map>
deba@1705:     struct Ref<XMap<Map> > { 
deba@1705:       typedef XMap<Map> Type;
deba@1705:     };
deba@1705:     template <typename Map>
deba@1705:     struct Ref<ConstXMap<Map> > { 
deba@1705:       typedef ConstXMap<Map> Type;
deba@1705:     };
deba@1705: 
deba@1705:     template <typename Map>
deba@1705:     struct Ref<YMap<Map> > { 
deba@1705:       typedef YMap<Map> Type;
deba@1705:     };
deba@1705:     template <typename Map>
deba@1705:     struct Ref<ConstYMap<Map> > { 
deba@1705:       typedef ConstYMap<Map> Type;
deba@1705:     };
deba@1705: 
deba@1845: 
deba@1845:     template <typename _Item>    
deba@1845:     class MapWriterBase {
deba@1845:     public:
deba@1845:       typedef _Item Item;
deba@1845: 
deba@1845:       virtual ~MapWriterBase() {}
deba@1845: 
deba@1852:       virtual void write(std::ostream& os, const Item& item) const = 0;
deba@1845:     };
deba@1845: 
deba@1845: 
deba@1845:     template <typename _Item, typename _Map, typename _Writer>
deba@1845:     class MapWriter : public MapWriterBase<_Item> {
deba@1845:     public:
deba@1845:       typedef _Map Map;
deba@1845:       typedef _Writer Writer;
deba@1845:       typedef typename Writer::Value Value;
deba@1845:       typedef _Item Item;
deba@1845:       
deba@1845:       typename _writer_bits::Ref<Map>::Type map;
deba@1845:       Writer writer;
deba@1845: 
deba@1845:       MapWriter(const Map& _map, const Writer& _writer) 
deba@1845: 	: map(_map), writer(_writer) {}
deba@1845: 
deba@1845:       virtual ~MapWriter() {}
deba@1845: 
deba@1852:       virtual void write(std::ostream& os, const Item& item) const {
deba@1845: 	Value value = map[item];
deba@1845: 	writer.write(os, value);
deba@1845:       }
deba@1845: 
deba@1845:     };
deba@1845: 
deba@1845: 
deba@1845:     class ValueWriterBase {
deba@1845:     public:
deba@1845:       virtual ~ValueWriterBase() {}
deba@1845:       virtual void write(std::ostream&) = 0;
deba@1845:     };
deba@1845: 
deba@1845:     template <typename _Value, typename _Writer>
deba@1845:     class ValueWriter : public ValueWriterBase {
deba@1845:     public:
deba@1845:       typedef _Value Value;
deba@1845:       typedef _Writer Writer;
deba@1845: 
deba@1845:       ValueWriter(const Value& _value, const Writer& _writer)
deba@1845:  	: value(_value), writer(_writer) {}
deba@1845: 
deba@1845:       virtual void write(std::ostream& os) {
deba@1845: 	writer.write(os, value);
deba@1845:       }
deba@1845:     private:
deba@1845:       const Value& value;
deba@1845:       Writer writer;
deba@1845:     };
deba@1845:     
deba@1845: 
deba@1845:     template <typename _Item>
deba@1901:     class LabelWriterBase {
deba@1845:     public:
deba@1845:       typedef _Item Item;
deba@1901:       virtual ~LabelWriterBase() {}
deba@1845:       virtual void write(std::ostream&, const Item&) const = 0;
deba@1901:       virtual bool isLabelWriter() const = 0;
deba@1845:     };
deba@1845: 
deba@1901:     template <typename _Item, typename _BoxedLabelWriter>
deba@1901:     class LabelWriter : public LabelWriterBase<_Item> {
deba@1845:     public:
deba@1845:       typedef _Item Item;
deba@1901:       typedef _BoxedLabelWriter BoxedLabelWriter;
deba@1845: 
deba@1901:       const BoxedLabelWriter& labelWriter;
deba@1845: 
deba@1901:       LabelWriter(const BoxedLabelWriter& _labelWriter) 
deba@1901: 	: labelWriter(_labelWriter) {}
deba@1845: 
deba@1845:       virtual void write(std::ostream& os, const Item& item) const {
deba@1901: 	labelWriter.writeLabel(os, item);
deba@1845:       }
deba@1845: 
deba@1901:       virtual bool isLabelWriter() const {
deba@1901: 	return labelWriter.isLabelWriter();
deba@1845:       }
deba@1845:     };
deba@1845: 
deba@1476:   }
deba@1476: 
deba@1409:   /// \ingroup io_group
deba@1409:   /// \brief Lemon Format writer class.
deba@1409:   /// 
deba@1409:   /// The Lemon Format contains several sections. We do not want to
deba@1409:   /// determine what sections are in a lemon file we give only a framework
deba@1409:   /// to write a section oriented format.
deba@1409:   ///
deba@1409:   /// In the Lemon Format each section starts with a line contains a \c \@
deba@1409:   /// character on the first not white space position. This line is the
deba@1409:   /// header line of the section. Each next lines belong to this section
deba@1409:   /// while it does not starts with \c \@ character. This line can start a 
deba@1409:   /// new section or if it can close the file with the \c \@end line.
deba@1409:   /// The file format ignore the empty lines and it may contain comments
deba@1409:   /// started with a \c # character to the end of the line. 
deba@1409:   ///
deba@1409:   /// The framework provides an abstract LemonWriter::SectionWriter class
deba@1409:   /// what defines the interface of a SectionWriter. The SectionWriter
deba@1409:   /// has the \c header() member function what gives back the header of the
deba@1409:   /// section. After that it will be called the \c write() member which
deba@1409:   /// should write the content of the section.
deba@1409:   ///
deba@1409:   /// \relates GraphWriter
deba@1409:   /// \relates NodeSetWriter
deba@1409:   /// \relates EdgeSetWriter
deba@1409:   /// \relates NodesWriter
deba@1409:   /// \relates EdgesWriter
deba@1409:   /// \relates AttributeWriter
deba@1409:   class LemonWriter {
deba@1409:   public:
deba@1409: 
deba@1409:     /// \brief Abstract base class for writing a section.
deba@1409:     ///
deba@1409:     /// This class has an \c header() member function what gives back
deba@1409:     /// the header line of the section. The \c write() member should
deba@1409:     /// write the content of the section to the stream.
deba@1409:     class SectionWriter {
deba@1409:       friend class LemonWriter;
deba@1409:     protected:
deba@1409:       /// \brief Constructor for SectionWriter.
deba@1409:       ///
deba@1409:       /// Constructor for SectionWriter. It attach this writer to
deba@1409:       /// the given LemonWriter.
deba@1409:       SectionWriter(LemonWriter& writer) {
deba@1409: 	writer.attach(*this);
deba@1409:       }
alpar@1494:       
alpar@1494:       virtual ~SectionWriter() {}
deba@1409: 
deba@1409:       /// \brief The header of section.
deba@1409:       ///
deba@1409:       /// It gives back the header of the section.
deba@1409:       virtual std::string header() = 0;
deba@1409: 
deba@1409:       /// \brief  Writer function of the section.
deba@1409:       ///
deba@1409:       /// Write the content of the section.
deba@1409:       virtual void write(std::ostream& os) = 0;
deba@1409:     };
deba@1409: 
deba@1409:     /// \brief Constructor for LemonWriter.
deba@1409:     ///
deba@1409:     /// Constructor for LemonWriter which writes to the given stream.
deba@1409:     LemonWriter(std::ostream& _os) 
deba@1409:       : os(&_os), own_os(false) {}
deba@1409: 
deba@1409:     /// \brief Constructor for LemonWriter.
deba@1409:     ///
deba@1409:     /// Constructor for LemonWriter which writes to the given file.
deba@1409:     LemonWriter(const std::string& filename) 
deba@1409:       : os(0), own_os(true) {
deba@1409:       os = new std::ofstream(filename.c_str());
deba@1409:     }
deba@1409: 
deba@1409:     /// \brief Desctructor for LemonWriter.
deba@1409:     ///
deba@1409:     /// Desctructor for LemonWriter.
deba@1409:     ~LemonWriter() {
deba@1409:       if (own_os) {
deba@1409: 	delete os;
deba@1409:       }
deba@1409:     }
deba@1409: 
deba@1409:   private:
deba@1409:     LemonWriter(const LemonWriter&);
deba@1409:     void operator=(const LemonWriter&);
deba@1409: 
deba@1409:     void attach(SectionWriter& writer) {
deba@1409:       writers.push_back(&writer);
deba@1409:     }
deba@1409: 
deba@1409:   public:
deba@1409: 
deba@1409:     /// \brief Executes the LemonWriter.
deba@1409:     /// 
deba@1409:     /// It executes the LemonWriter.
deba@1409:     void run() {
deba@1409:       SectionWriters::iterator it;
deba@1409:       for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409: 	*os << (*it)->header() << std::endl;
deba@1409: 	(*it)->write(*os);
deba@1409:       }
deba@1409:       *os << "@end" << std::endl;
deba@1409:     }
deba@1409: 
deba@1409: 
deba@1409:   private:
deba@1409: 
deba@1409:     std::ostream* os;
deba@1409:     bool own_os;
deba@1409: 
deba@1409:     typedef std::vector<SectionWriter*> SectionWriters;
deba@1409:     SectionWriters writers;
deba@1409: 
deba@1409:   };
deba@1409: 
deba@1409:   /// \ingroup io_group
deba@1409:   /// \brief SectionWriter for writing a graph's nodeset.
deba@1409:   ///
deba@1409:   /// The lemon format can store multiple graph nodesets with several maps.
deba@1901:   /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but 
deba@1901:   /// the \c nodeset_name may be empty.
deba@1409:   ///
deba@1409:   /// The first line of the section contains the names of the maps separated
deba@1409:   /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409:   /// contains the mapped values for each map.
deba@1409:   ///
deba@1901:   /// If the nodeset contains an \c "label" named map then it will be regarded
deba@1901:   /// as label map. This map should contain only unique values and when the 
deba@1901:   /// \c writeLabel() member will be called with a node it will write it's 
deba@1901:   /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
deba@1901:   /// then the label map will be the id in the graph.
deba@1409:   ///
deba@1409:   /// \relates LemonWriter
deba@1409:   template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1845:   class NodeSetWriter : public LemonWriter::SectionWriter {
deba@1845:     typedef LemonWriter::SectionWriter Parent;
deba@1409:   public:
deba@1409: 
deba@1409:     typedef _Graph Graph;
deba@1409:     typedef _Traits Traits;
deba@1429:     typedef typename Graph::Node Node;
deba@1409: 
deba@1409:     /// \brief Constructor.
deba@1409:     ///
deba@1409:     /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
deba@1901:     /// attach it into the given LemonWriter. If the \c _forceLabelMap
deba@1901:     /// parameter is true then the writer will write own label map when
deba@1901:     /// the user does not give "label" named map.
deba@1409:     NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1901: 		  const std::string& _name = std::string(), 
deba@1901: 		  bool _forceLabelMap = true) 
deba@1901:       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), 
deba@1901: 	graph(_graph), name(_name) {}
deba@1409: 
deba@1409:     /// \brief Destructor.
deba@1409:     ///
deba@1409:     /// Destructor for NodeSetWriter.
deba@1409:     virtual ~NodeSetWriter() {
deba@1409:       typename MapWriters::iterator it;
deba@1409:       for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409: 	delete it->second;
deba@1409:       }
deba@1409:     }
deba@1409: 
deba@1409:   private:
deba@1409:     NodeSetWriter(const NodeSetWriter&);
deba@1409:     void operator=(const NodeSetWriter&);
deba@1409:   
deba@1409:   public:
deba@1409: 
deba@1409:     /// \brief Add a new node map writer command for the writer.
deba@1409:     ///
deba@1409:     /// Add a new node map writer command for the writer.
deba@1409:     template <typename Map>
deba@1421:     NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
deba@1421:       return writeNodeMap<typename Traits::
deba@1409: 	template Writer<typename Map::Value>, Map>(name, map);
deba@1409:     }
deba@1409: 
deba@1409:     /// \brief Add a new node map writer command for the writer.
deba@1409:     ///
deba@1409:     /// Add a new node map writer command for the writer.
deba@1409:     template <typename Writer, typename Map>
deba@1421:     NodeSetWriter& writeNodeMap(std::string name, const Map& map, 
deba@1421: 			    const Writer& writer = Writer()) {
deba@1492:       checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
deba@1492:       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@1409:       writers.push_back(
deba@1845: 	make_pair(name, new _writer_bits::
deba@1845: 		  MapWriter<Node, Map, Writer>(map, writer)));
deba@1409:       return *this;
deba@1409:     }
deba@1409: 
deba@1409:   protected:
deba@1409: 
deba@1409:     /// \brief The header of the section.
deba@1409:     ///
deba@1409:     /// It gives back the header of the section.
deba@1409:     virtual std::string header() {
deba@1901:       return "@nodeset " + name;
deba@1409:     }
deba@1409: 
deba@1409:     /// \brief  Writer function of the section.
deba@1409:     ///
deba@1409:     /// Write the content of the section.
deba@1409:     virtual void write(std::ostream& os) {
deba@1409:       for (int i = 0; i < (int)writers.size(); ++i) {
deba@1901: 	if (writers[i].first == "label" || (writers[i].first == "id" && labelMap == 0)) {
deba@1901: 	  labelMap = writers[i].second;
deba@1901: 	  forceLabelMap = false;
deba@1409: 	  break;
deba@1409: 	}
deba@1409:       }
deba@1901:       if (forceLabelMap) {
deba@1901: 	os << "label\t";
deba@1409:       }
deba@1409:       for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409: 	os << writers[i].first << '\t';
deba@1409:       }
deba@1409:       os << std::endl;
deba@1409:       for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
deba@1901: 	if (forceLabelMap) {
deba@1409: 	  os << graph.id(it) << '\t';
deba@1409: 	}
deba@1409: 	for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409: 	  writers[i].second->write(os, it);
deba@1409: 	  os << '\t';
deba@1409: 	}
deba@1409: 	os << std::endl;
deba@1409:       }
deba@1409:     }
deba@1409: 
deba@1409:   public:
deba@1409: 
deba@1901:     /// \brief Returns true if the nodeset can write the labels of the nodes.
deba@1409:     ///
deba@1901:     /// Returns true if the nodeset can write the labels of the nodes.
deba@1901:     /// It is possible only if an "label" named map was written or the 
deba@1901:     /// \c _forceLabelMap constructor parameter was true.
deba@1901:     bool isLabelWriter() const {
deba@1901:       return labelMap != 0 || forceLabelMap;
deba@1409:     }
deba@1409: 
deba@1901:     /// \brief Write the label of the given node.
deba@1409:     ///
deba@1901:     /// It writes the label of the given node. If there was written an "label"
deba@1409:     /// named map then it will write the map value belongs to the node.
deba@1901:     /// Otherwise if the \c forceLabel parameter was true it will write
deba@1901:     /// its label in the graph. 
deba@1901:     void writeLabel(std::ostream& os, const Node& item) const {
deba@1901:       if (forceLabelMap) {
deba@1409: 	os << graph.id(item);
deba@1409:       } else {
deba@1901: 	labelMap->write(os, item);
deba@1409:       }
deba@1409:     }
deba@1409: 
deba@1409:   private:
deba@1409: 
deba@1845:     typedef std::vector<std::pair<std::string, _writer_bits::
deba@1845: 				  MapWriterBase<Node>*> > MapWriters;
deba@1409:     MapWriters writers;
deba@1409: 
deba@1901:     _writer_bits::MapWriterBase<Node>* labelMap;
deba@1901:     bool forceLabelMap;
deba@1409:    
deba@1705:     const Graph& graph;   
deba@1901:     std::string name;
deba@1409: 
deba@1409:   };
deba@1409: 
deba@1409:   /// \ingroup io_group
deba@1421:   /// \brief SectionWriter for writing a graph's edgesets.
deba@1409:   ///
deba@1421:   /// The lemon format can store multiple graph edgesets with several maps. 
deba@1901:   /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but 
deba@1901:   /// the \c edgeset_name may be empty.
deba@1409:   ///
deba@1409:   /// The first line of the section contains the names of the maps separated
deba@1409:   /// with white spaces. Each next lines describes a edge in the edgeset. The
deba@1901:   /// line contains the source and the target nodes' label and the mapped 
deba@1409:   /// values for each map.
deba@1409:   ///
deba@1901:   /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1901:   /// as label map. This map should contain only unique values and when the 
deba@1901:   /// \c writeLabel() member will be called with an edge it will write it's 
deba@1901:   /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
deba@1901:   /// then the label map will be the id in the graph.
deba@1409:   ///
deba@1901:   /// The edgeset writer needs a node label writer to identify which nodes
deba@1901:   /// have to be connected. If a NodeSetWriter can write the nodes' label,
deba@1409:   /// it will be able to use with this class.
deba@1409:   ///
deba@1409:   /// \relates LemonWriter
deba@1409:   template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1845:   class EdgeSetWriter : public LemonWriter::SectionWriter {
deba@1845:     typedef LemonWriter::SectionWriter Parent;
deba@1409:   public:
deba@1409: 
deba@1409:     typedef _Graph Graph;
deba@1409:     typedef _Traits Traits;
deba@1429:     typedef typename Graph::Node Node;
deba@1429:     typedef typename Graph::Edge Edge;
deba@1409: 
deba@1409:     /// \brief Constructor.
deba@1409:     ///
deba@1409:     /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
deba@1901:     /// attach it into the given LemonWriter. It will write node labels by
deba@1901:     /// the \c _nodeLabelWriter. If the \c _forceLabelMap parameter is true 
deba@1901:     /// then the writer will write own label map if the user does not give 
deba@1901:     /// "label" named map.
deba@1901:     template <typename NodeLabelWriter>
deba@1409:     EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1901: 		  const NodeLabelWriter& _nodeLabelWriter, 
deba@1901: 		  const std::string& _name = std::string(),
deba@1901: 		  bool _forceLabelMap = true)
deba@1901:       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
deba@1901: 	graph(_graph), name(_name) {
deba@1901:       checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
deba@1901:       nodeLabelWriter.reset(new _writer_bits::
deba@1901: 			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
deba@1476:     } 
deba@1409: 
deba@1409:     /// \brief Destructor.
deba@1409:     ///
deba@1409:     /// Destructor for EdgeSetWriter.
deba@1409:     virtual ~EdgeSetWriter() {
deba@1409:       typename MapWriters::iterator it;
deba@1409:       for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409: 	delete it->second;
deba@1409:       }
deba@1409:     }
deba@1409: 
deba@1409:   private:
deba@1409:     EdgeSetWriter(const EdgeSetWriter&);
deba@1409:     void operator=(const EdgeSetWriter&);
deba@1409: 
deba@1409:   public:
deba@1409: 
deba@1421:     /// \brief Add a new edge map writer command for the writer.
deba@1409:     ///
deba@1421:     /// Add a new edge map writer command for the writer.
deba@1409:     template <typename Map>
deba@1421:     EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
deba@1421:       return writeEdgeMap<typename Traits::
deba@1409: 	template Writer<typename Map::Value>, Map>(name, map);
deba@1409:     }
deba@1409: 
deba@1421:     /// \brief Add a new edge map writer command for the writer.
deba@1409:     ///
deba@1421:     /// Add a new edge map writer command for the writer.
deba@1409:     template <typename Writer, typename Map>
deba@1421:     EdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
deba@1421: 			    const Writer& writer = Writer()) {
deba@1492:       checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
deba@1492:       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@1409:       writers.push_back(
deba@1845: 	make_pair(name, new _writer_bits::
deba@1845: 		  MapWriter<Edge, Map, Writer>(map, writer)));
deba@1409:       return *this;
deba@1409:     }
deba@1409: 
deba@1409:   protected:
deba@1409: 
deba@1409:     /// \brief The header of the section.
deba@1409:     ///
deba@1409:     /// It gives back the header of the section.
deba@1409:     virtual std::string header() {
deba@1901:       return "@edgeset " + name;
deba@1409:     }
deba@1409: 
deba@1409:     /// \brief  Writer function of the section.
deba@1409:     ///
deba@1409:     /// Write the content of the section.
deba@1409:     virtual void write(std::ostream& os) {
deba@1901:       if (!nodeLabelWriter->isLabelWriter()) {
deba@1901: 	throw DataFormatError("Cannot find nodeset or label map");
deba@1476:       }
deba@1409:       for (int i = 0; i < (int)writers.size(); ++i) {
deba@1901: 	if (writers[i].first == "label" || (writers[i].first == "id" && labelMap == 0)) {
deba@1901: 	  labelMap = writers[i].second;
deba@1901: 	  forceLabelMap = false;
deba@1409: 	  break;
deba@1409: 	}
deba@1409:       }
deba@1409:       os << "\t\t";
deba@1901:       if (forceLabelMap) {
deba@1901: 	os << "label\t";
deba@1409:       }
deba@1409:       for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409: 	os << writers[i].first << '\t';
deba@1409:       }
deba@1409:       os << std::endl;
deba@1409:       for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
deba@1901: 	nodeLabelWriter->write(os, graph.source(it));
deba@1409: 	os << '\t';
deba@1901: 	nodeLabelWriter->write(os, graph.target(it));
deba@1409: 	os << '\t';
deba@1901: 	if (forceLabelMap) {
deba@1409: 	  os << graph.id(it) << '\t';
deba@1409: 	}
deba@1409: 	for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409: 	  writers[i].second->write(os, it);
deba@1409: 	  os << '\t';
deba@1409: 	}
deba@1409: 	os << std::endl;
deba@1409:       }
deba@1409:     }
deba@1409: 
deba@1409:   public:
deba@1409: 
deba@1901:     /// \brief Returns true if the edgeset can write the labels of the edges.
deba@1409:     ///
deba@1901:     /// Returns true if the edgeset can write the labels of the edges.
deba@1901:     /// It is possible only if an "label" named map was written or the 
deba@1901:     /// \c _forceLabelMap constructor parameter was true.
deba@1901:     bool isLabelWriter() const {
deba@1901:       return forceLabelMap || labelMap != 0;
deba@1409:     }
deba@1409: 
deba@1901:     /// \brief Write the label of the given edge.
deba@1409:     ///
deba@1901:     /// It writes the label of the given edge. If there was written an "label"
deba@1409:     /// named map then it will write the map value belongs to the edge.
deba@1901:     /// Otherwise if the \c forceLabel parameter was true it will write
deba@1901:     /// its label in the graph. 
deba@1901:     void writeLabel(std::ostream& os, const Edge& item) const {
deba@1901:       if (forceLabelMap) {
deba@1409: 	os << graph.id(item);
deba@1409:       } else {
deba@1901: 	labelMap->write(os, item);
deba@1409:       }
deba@1409:     } 
deba@1409: 
deba@1409:   private:
deba@1409: 
deba@1845:     typedef std::vector<std::pair<std::string, _writer_bits::
deba@1845: 				  MapWriterBase<Edge>*> > MapWriters;
deba@1409:     MapWriters writers;
deba@1409: 
deba@1901:     _writer_bits::MapWriterBase<Edge>* labelMap;
deba@1901:     bool forceLabelMap;
deba@1409:    
deba@1705:     const Graph& graph;   
deba@1901:     std::string name;
deba@1421: 
deba@1901:     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
deba@1421:   };
deba@1421: 
deba@1421:   /// \ingroup io_group
deba@1421:   /// \brief SectionWriter for writing a undirected edgeset.
deba@1421:   ///
deba@1421:   /// The lemon format can store multiple undirected edgesets with several 
klao@1909:   /// maps. The undirected edgeset section's header line is \c \@uedgeset 
klao@1909:   /// \c uedgeset_name, but the \c uedgeset_name may be empty.
deba@1421:   ///
deba@1421:   /// The first line of the section contains the names of the maps separated
deba@1421:   /// with white spaces. Each next lines describes an undirected edge in the 
deba@1901:   /// edgeset. The line contains the two connected nodes' label and the mapped 
deba@1421:   /// values for each undirected map.
deba@1421:   ///
deba@1421:   /// The section can handle the directed as a syntactical sugar. Two
deba@1421:   /// undirected edge map describes one directed edge map. This two maps
deba@1421:   /// are the forward map and the backward map and the names of this map
deba@1421:   /// is near the same just with a prefix \c '+' or \c '-' character 
deba@1421:   /// difference.
deba@1421:   ///
deba@1901:   /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1901:   /// as label map. This map should contain only unique values and when the 
deba@1901:   /// \c writeLabel() member will be called with an undirected edge it will 
deba@1901:   /// write it's label. Otherwise if the \c _forceLabelMap constructor 
deba@1901:   /// parameter is true then the label map will be the id in the graph.
deba@1421:   ///
deba@1901:   /// The undirected edgeset writer needs a node label writer to identify 
deba@1421:   /// which nodes have to be connected. If a NodeSetWriter can write the 
deba@1901:   /// nodes' label, it will be able to use with this class.
deba@1421:   ///
deba@1421:   /// \relates LemonWriter
deba@1421:   template <typename _Graph, typename _Traits = DefaultWriterTraits>
klao@1909:   class UEdgeSetWriter : public LemonWriter::SectionWriter {
deba@1845:     typedef LemonWriter::SectionWriter Parent;
deba@1421:   public:
deba@1421: 
deba@1421:     typedef _Graph Graph;
deba@1421:     typedef _Traits Traits;
deba@1429:     typedef typename Graph::Node Node;
deba@1429:     typedef typename Graph::Edge Edge;
klao@1909:     typedef typename Graph::UEdge UEdge;
deba@1421: 
deba@1421:     /// \brief Constructor.
deba@1421:     ///
klao@1909:     /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
deba@1901:     /// and attach it into the given LemonWriter. It will write node labels by
deba@1901:     /// the \c _nodeLabelWriter. If the \c _forceLabelMap parameter is true 
deba@1901:     /// then the writer will write own label map if the user does not give 
deba@1901:     /// "label" named map.
deba@1901:     template <typename NodeLabelWriter>
klao@1909:     UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1901: 		       const NodeLabelWriter& _nodeLabelWriter, 
deba@1901: 		       const std::string& _name = std::string(),
deba@1901: 		       bool _forceLabelMap = true)
deba@1901:       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
deba@1901: 	graph(_graph), name(_name) {
deba@1901:       checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
deba@1901:       nodeLabelWriter.reset(new _writer_bits::
deba@1901: 			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
deba@1476:     } 
deba@1421: 
deba@1421:     /// \brief Destructor.
deba@1421:     ///
klao@1909:     /// Destructor for UEdgeSetWriter.
klao@1909:     virtual ~UEdgeSetWriter() {
deba@1421:       typename MapWriters::iterator it;
deba@1421:       for (it = writers.begin(); it != writers.end(); ++it) {
deba@1421: 	delete it->second;
deba@1421:       }
deba@1421:     }
deba@1421: 
deba@1421:   private:
klao@1909:     UEdgeSetWriter(const UEdgeSetWriter&);
klao@1909:     void operator=(const UEdgeSetWriter&);
deba@1421: 
deba@1421:   public:
deba@1421: 
deba@1421:     /// \brief Add a new undirected edge map writer command for the writer.
deba@1421:     ///
deba@1421:     /// Add a new undirected map writer command for the writer.
deba@1421:     template <typename Map>
klao@1909:     UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map) {
klao@1909:       return writeUEdgeMap<typename Traits::
deba@1421: 	template Writer<typename Map::Value>, Map>(name, map);
deba@1421:     }
deba@1421: 
deba@1421:     /// \brief Add a new undirected map writer command for the writer.
deba@1421:     ///
deba@1421:     /// Add a new undirected map writer command for the writer.
deba@1421:     template <typename Writer, typename Map>
klao@1909:     UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map, 
deba@1421: 					  const Writer& writer = Writer()) {
klao@1909:       checkConcept<concept::ReadMap<UEdge, typename Map::Value>, Map>();
deba@1492:       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@1421:       writers.push_back(
deba@1845: 	make_pair(name, new _writer_bits::
klao@1909: 		  MapWriter<UEdge, Map, Writer>(map, writer)));
deba@1421:       return *this;
deba@1421:     }
deba@1421: 
deba@1421:     /// \brief Add a new directed edge map writer command for the writer.
deba@1421:     ///
deba@1421:     /// Add a new directed map writer command for the writer.
deba@1421:     template <typename Map>
klao@1909:     UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
deba@1492:       return writeEdgeMap<typename Traits::
deba@1492: 	template Writer<typename Map::Value>, Map>(name, map);
deba@1421:     }
deba@1421: 
deba@1421:     /// \brief Add a new directed map writer command for the writer.
deba@1421:     ///
deba@1421:     /// Add a new directed map writer command for the writer.
deba@1421:     template <typename Writer, typename Map>
klao@1909:     UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
deba@1421: 				     const Writer& writer = Writer()) {
deba@1492:       checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
deba@1492:       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
klao@1909:       writeUEdge("+" + name, 
deba@1705: 		     _writer_bits::forwardComposeMap(graph, map), writer);
klao@1909:       writeUEdge("-" + name, 
deba@1705: 		     _writer_bits::backwardComposeMap(graph, map), writer);
deba@1421:       return *this;
deba@1421:     }
deba@1421: 
deba@1421:   protected:
deba@1421: 
deba@1421:     /// \brief The header of the section.
deba@1421:     ///
deba@1421:     /// It gives back the header of the section.
deba@1421:     virtual std::string header() {
klao@1909:       return "@uedgeset " + name;
deba@1421:     }
deba@1421: 
deba@1421:     /// \brief  Writer function of the section.
deba@1421:     ///
deba@1421:     /// Write the content of the section.
deba@1421:     virtual void write(std::ostream& os) {
deba@1901:       if (!nodeLabelWriter->isLabelWriter()) {
deba@1901: 	throw DataFormatError("Cannot find nodeset or label map");
deba@1476:       }
deba@1421:       for (int i = 0; i < (int)writers.size(); ++i) {
deba@1901: 	if (writers[i].first == "label") {
deba@1901: 	  labelMap = writers[i].second;
deba@1901: 	  forceLabelMap = false;
deba@1421: 	  break;
deba@1421: 	}
deba@1421:       }
deba@1421:       os << "\t\t";
deba@1901:       if (forceLabelMap) {
deba@1901: 	os << "label\t";
deba@1421:       }
deba@1421:       for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421: 	os << writers[i].first << '\t';
deba@1421:       }
deba@1421:       os << std::endl;
klao@1909:       for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
deba@1901: 	nodeLabelWriter->write(os, graph.source(it));
deba@1421: 	os << '\t';
deba@1901: 	nodeLabelWriter->write(os, graph.target(it));
deba@1421: 	os << '\t';
deba@1901: 	if (forceLabelMap) {
deba@1421: 	  os << graph.id(it) << '\t';
deba@1421: 	}
deba@1421: 	for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421: 	  writers[i].second->write(os, it);
deba@1421: 	  os << '\t';
deba@1421: 	}
deba@1421: 	os << std::endl;
deba@1421:       }
deba@1421:     }
deba@1421: 
deba@1421:   public:
deba@1421: 
deba@1901:     /// \brief Returns true if the undirected edgeset can write the labels of 
deba@1421:     /// the edges.
deba@1421:     ///
deba@1901:     /// Returns true if the undirected edgeset can write the labels of the 
deba@1901:     /// undirected edges. It is possible only if an "label" named map was 
deba@1901:     /// written or the \c _forceLabelMap constructor parameter was true.
deba@1901:     bool isLabelWriter() const {
deba@1901:       return forceLabelMap || labelMap != 0;
deba@1421:     }
deba@1421: 
deba@1901:     /// \brief Write the label of the given undirected edge.
deba@1421:     ///
deba@1901:     /// It writes the label of the given undirected edge. If there was written 
deba@1901:     /// an "label" named map then it will write the map value belongs to the 
deba@1901:     /// undirected edge. Otherwise if the \c forceLabel parameter was true it 
deba@1421:     /// will write its id in the graph. 
klao@1909:     void writeLabel(std::ostream& os, const UEdge& item) const {
deba@1901:       if (forceLabelMap) {
deba@1429: 	os << graph.id(item);
deba@1429:       } else {
deba@1901: 	labelMap->write(os, item);
deba@1429:       }
deba@1429:     } 
deba@1429: 
deba@1901:     /// \brief Write the label of the given edge.
deba@1429:     ///
deba@1901:     /// It writes the label of the given edge. If there was written 
deba@1901:     /// an "label" named map then it will write the map value belongs to the 
deba@1901:     /// edge. Otherwise if the \c forceLabel parameter was true it 
deba@1429:     /// will write its id in the graph. If the edge is forward map
deba@1429:     /// then its prefix character is \c '+' elsewhere \c '-'.
deba@1901:     void writeLabel(std::ostream& os, const Edge& item) const {
deba@1690:       if (graph.direction(item)) {
deba@1429: 	os << "+ ";
deba@1429:       } else {
deba@1429: 	os << "- ";
deba@1429:       }
deba@1901:       if (forceLabelMap) {
deba@1421: 	os << graph.id(item);
deba@1421:       } else {
deba@1901: 	labelMap->write(os, item);
deba@1421:       }
deba@1421:     } 
deba@1421: 
deba@1421:   private:
deba@1421: 
deba@1845:     typedef std::vector<std::pair<std::string, _writer_bits::
klao@1909: 				  MapWriterBase<UEdge>*> > MapWriters;
deba@1421:     MapWriters writers;
deba@1421: 
klao@1909:     _writer_bits::MapWriterBase<UEdge>* labelMap;
deba@1901:     bool forceLabelMap;
deba@1421:    
deba@1705:     const Graph& graph;   
deba@1901:     std::string name;
deba@1409: 
deba@1901:     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
deba@1409:   };
deba@1409: 
deba@1409:   /// \ingroup io_group
deba@1901:   /// \brief SectionWriter for writing named nodes.
deba@1409:   ///
deba@1901:   /// The nodes section's header line is \c \@nodes \c nodes_name, but the
deba@1901:   /// \c nodes_name may be empty.
deba@1409:   ///
deba@1901:   /// Each line in the section contains the name of the node and 
deba@1901:   /// then the node label. 
deba@1409:   ///
deba@1409:   /// \relates LemonWriter
deba@1409:   template <typename _Graph>
deba@1845:   class NodeWriter : public LemonWriter::SectionWriter {
deba@1845:     typedef LemonWriter::SectionWriter Parent;
deba@1409:     typedef _Graph Graph;
deba@1429:     typedef typename Graph::Node Node;
deba@1409:   public:
deba@1409:     
deba@1409:     /// \brief Constructor.
deba@1409:     ///
deba@1409:     /// Constructor for NodeWriter. It creates the NodeWriter and
deba@1901:     /// attach it into the given LemonWriter. The given \c _LabelWriter
deba@1901:     /// will write the nodes' label what can be a nodeset writer.
deba@1901:     template <typename _LabelWriter>
deba@1901:     NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
deba@1901: 	       const std::string& _name = std::string()) 
deba@1901:       : Parent(_writer), name(_name) {
deba@1901:       checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
deba@1901:       labelWriter.reset(new _writer_bits::LabelWriter<Node, _LabelWriter>
deba@1901:                         (_labelWriter));
deba@1476:     }
deba@1476: 
deba@1409: 
deba@1409:     /// \brief Destructor.
deba@1409:     ///
deba@1409:     /// Destructor for NodeWriter.
deba@1409:     virtual ~NodeWriter() {}
deba@1409: 
deba@1409:   private:
deba@1409:     NodeWriter(const NodeWriter&);
deba@1409:     void operator=(const NodeWriter&);
deba@1409: 
deba@1409:   public:
deba@1409: 
deba@1409:     /// \brief Add a node writer command for the NodeWriter.
deba@1409:     ///
deba@1409:     /// Add a node writer command for the NodeWriter.
deba@1429:     void writeNode(const std::string& name, const Node& item) {
deba@1409:       writers.push_back(make_pair(name, &item));
deba@1409:     }
deba@1409: 
deba@1409:   protected:
deba@1409: 
deba@1901:     /// \brief The header of the section.
deba@1409:     ///
deba@1901:     /// It gives back the header of the section.
deba@1409:     virtual std::string header() {
deba@1901:       return "@nodes " + name;
deba@1409:     }
deba@1409: 
deba@1409:     /// \brief  Writer function of the section.
deba@1409:     ///
deba@1409:     /// Write the content of the section.
deba@1409:     virtual void write(std::ostream& os) {
deba@1901:       if (!labelWriter->isLabelWriter()) {
deba@1901: 	throw DataFormatError("Cannot find nodeset or label map");
deba@1476:       }
deba@1409:       for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409: 	os << writers[i].first << ' ';
deba@1901: 	labelWriter->write(os, *(writers[i].second));
deba@1409: 	os << std::endl;
deba@1409:       }
deba@1409:     }
deba@1409:     
deba@1409:   private:
deba@1409: 
deba@1901:     std::string name;
deba@1409: 
deba@1429:     typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
deba@1429:     NodeWriters writers;
deba@1901:     std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
deba@1409:   };
deba@1409: 
deba@1409:   /// \ingroup io_group
deba@1901:   /// \brief SectionWriter for writing named edges.
deba@1409:   ///
deba@1901:   /// The edges section's header line is \c \@edges \c edges_name, but the
deba@1901:   /// \c edges_name may be empty.
deba@1409:   ///
deba@1901:   /// Each line in the section contains the name of the edge and 
deba@1901:   /// then the edge label. 
deba@1409:   ///
deba@1409:   /// \relates LemonWriter
deba@1409:   template <typename _Graph>
deba@1845:   class EdgeWriter : public LemonWriter::SectionWriter {
deba@1845:     typedef LemonWriter::SectionWriter Parent;
deba@1409:     typedef _Graph Graph;
deba@1429:     typedef typename Graph::Edge Edge;
deba@1409:   public:
deba@1409:     
deba@1409:     /// \brief Constructor.
deba@1409:     ///
deba@1409:     /// Constructor for EdgeWriter. It creates the EdgeWriter and
deba@1901:     /// attach it into the given LemonWriter. The given \c _LabelWriter
deba@1901:     /// will write the edges' label what can be a edgeset writer.
deba@1901:     template <typename _LabelWriter>
deba@1901:     EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
deba@1901: 	       const std::string& _name = std::string()) 
deba@1901:       : Parent(_writer), name(_name) {
deba@1901:       checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
deba@1901:       labelWriter.reset(new _writer_bits::LabelWriter<Edge, _LabelWriter>(_labelWriter));
deba@1476:     }
deba@1409: 
deba@1409:     /// \brief Destructor.
deba@1409:     ///
deba@1409:     /// Destructor for EdgeWriter.
deba@1409:     virtual ~EdgeWriter() {}
deba@1409:   private:
deba@1409:     EdgeWriter(const EdgeWriter&);
deba@1409:     void operator=(const EdgeWriter&);
deba@1409: 
deba@1409:   public:
deba@1409: 
deba@1421:     /// \brief Add an edge writer command for the EdgeWriter.
deba@1409:     ///
deba@1421:     /// Add an edge writer command for the EdgeWriter.
deba@1429:     void writeEdge(const std::string& name, const Edge& item) {
deba@1409:       writers.push_back(make_pair(name, &item));
deba@1409:     }
deba@1409: 
deba@1409:   protected:
deba@1409: 
deba@1901:     /// \brief The header of the section.
deba@1409:     ///
deba@1901:     /// It gives back the header of the section.
deba@1421:     virtual std::string header() {
deba@1901:       return "@edges " + name;
deba@1421:     }
deba@1421: 
deba@1421:     /// \brief  Writer function of the section.
deba@1421:     ///
deba@1421:     /// Write the content of the section.
deba@1421:     virtual void write(std::ostream& os) {
deba@1901:       if (!labelWriter->isLabelWriter()) {
deba@1901: 	throw DataFormatError("Cannot find edgeset or label map");
deba@1476:       }
deba@1421:       for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421: 	os << writers[i].first << ' ';
deba@1901: 	labelWriter->write(os, *(writers[i].second));
deba@1421: 	os << std::endl;
deba@1421:       }
deba@1421:     }
deba@1421:     
deba@1421:   private:
deba@1421: 
deba@1901:     std::string name;
deba@1421: 
deba@1429:     typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
deba@1429:     EdgeWriters writers;
deba@1421: 
deba@1901:     std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
deba@1421:   };
deba@1421: 
deba@1421:   /// \ingroup io_group
deba@1901:   /// \brief SectionWriter for writing named undirected edges.
deba@1421:   ///
klao@1909:   /// The undirected edges section's header line is \c \@uedges 
klao@1909:   /// \c uedges_name, but the \c uedges_name may be empty.
deba@1421:   ///
deba@1901:   /// Each line in the section contains the name of the undirected edge and 
deba@1901:   /// then the undirected edge label. 
deba@1421:   ///
deba@1421:   /// \relates LemonWriter
deba@1421:   template <typename _Graph>
klao@1909:   class UEdgeWriter : public LemonWriter::SectionWriter {
deba@1845:     typedef LemonWriter::SectionWriter Parent;
deba@1421:     typedef _Graph Graph;
deba@1429:     typedef typename Graph::Node Node;
deba@1429:     typedef typename Graph::Edge Edge;
klao@1909:     typedef typename Graph::UEdge UEdge;
deba@1421:   public:
deba@1421:     
deba@1421:     /// \brief Constructor.
deba@1421:     ///
klao@1909:     /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
deba@1901:     /// attach it into the given LemonWriter. The given \c _LabelWriter
deba@1901:     /// will write the undirected edges' label what can be an undirected 
deba@1421:     /// edgeset writer.
deba@1901:     template <typename _LabelWriter>
klao@1909:     UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
deba@1901: 	       const std::string& _name = std::string()) 
deba@1901:       : Parent(_writer), name(_name) {
deba@1901:       checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
klao@1909:       checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
klao@1909:       uEdgeLabelWriter.reset(new _writer_bits::
klao@1909: 			      LabelWriter<UEdge, _LabelWriter>(_labelWriter));
deba@1901:       edgeLabelWriter.reset(new _writer_bits::
deba@1901: 			 LabelWriter<Edge, _LabelWriter>(_labelWriter));
deba@1476:     }
deba@1421: 
deba@1421:     /// \brief Destructor.
deba@1421:     ///
klao@1909:     /// Destructor for UEdgeWriter.
klao@1909:     virtual ~UEdgeWriter() {}
deba@1421:   private:
klao@1909:     UEdgeWriter(const UEdgeWriter&);
klao@1909:     void operator=(const UEdgeWriter&);
deba@1421: 
deba@1421:   public:
deba@1421: 
klao@1909:     /// \brief Add an edge writer command for the UEdgeWriter.
deba@1429:     ///
klao@1909:     /// Add an edge writer command for the UEdgeWriter.
deba@1429:     void writeEdge(const std::string& name, const Edge& item) {
deba@1429:       edgeWriters.push_back(make_pair(name, &item));
deba@1429:     }
deba@1429: 
klao@1909:     /// \brief Add an undirected edge writer command for the UEdgeWriter.
deba@1421:     ///
klao@1909:     /// Add an undirected edge writer command for the UEdgeWriter.
klao@1909:     void writeUEdge(const std::string& name, const UEdge& item) {
klao@1909:       uEdgeWriters.push_back(make_pair(name, &item));
deba@1421:     }
deba@1421: 
deba@1421:   protected:
deba@1421: 
deba@1901:     /// \brief The header of the section.
deba@1421:     ///
deba@1901:     /// It gives back the header of the section.
deba@1409:     virtual std::string header() {
klao@1909:       return "@uedges " + name;
deba@1409:     }
deba@1409: 
deba@1409:     /// \brief  Writer function of the section.
deba@1409:     ///
deba@1409:     /// Write the content of the section.
deba@1409:     virtual void write(std::ostream& os) {
deba@1901:       if (!edgeLabelWriter->isLabelWriter()) {
deba@1901: 	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476:       }
klao@1909:       if (!uEdgeLabelWriter->isLabelWriter()) {
deba@1901: 	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476:       }
klao@1909:       for (int i = 0; i < (int)uEdgeWriters.size(); ++i) {
klao@1909: 	os << uEdgeWriters[i].first << ' ';
klao@1909: 	uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
deba@1429: 	os << std::endl;
deba@1429:       }
deba@1429:       for (int i = 0; i < (int)edgeWriters.size(); ++i) {
deba@1429: 	os << edgeWriters[i].first << ' ';
deba@1901: 	edgeLabelWriter->write(os, *(edgeWriters[i].second));
deba@1409: 	os << std::endl;
deba@1409:       }
deba@1409:     }
deba@1409:     
deba@1409:   private:
deba@1409: 
deba@1901:     std::string name;
deba@1409: 
deba@1429:     typedef std::vector<std::pair<std::string, 
klao@1909: 				  const UEdge*> > UEdgeWriters;
klao@1909:     UEdgeWriters uEdgeWriters;
klao@1909:     std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
deba@1409: 
deba@1429:     typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
deba@1429:     EdgeWriters edgeWriters;
deba@1901:     std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
deba@1429: 
deba@1409:   };
deba@1409: 
deba@1409:   /// \ingroup io_group
deba@1409:   /// \brief SectionWriter for attributes.
deba@1409:   ///
deba@1409:   /// The lemon format can store multiple attribute set. Each set has
deba@1901:   /// the header line \c \@attributes \c attributes_name, but the 
deba@1901:   /// attributeset_name may be empty.
deba@1409:   ///
deba@1409:   /// The attributeset section contains several lines. Each of them starts
deba@1409:   /// with the name of attribute and then the value.
deba@1409:   ///
deba@1409:   /// \relates LemonWriter
deba@1409:   template <typename _Traits = DefaultWriterTraits>
deba@1845:   class AttributeWriter : public LemonWriter::SectionWriter {
deba@1845:     typedef LemonWriter::SectionWriter Parent;
deba@1409:     typedef _Traits Traits; 
deba@1409:   public:
deba@1409:     /// \brief Constructor.
deba@1409:     ///
deba@1409:     /// Constructor for AttributeWriter. It creates the AttributeWriter and
deba@1409:     /// attach it into the given LemonWriter.
deba@1409:     AttributeWriter(LemonWriter& _writer, 
deba@1901: 		    const std::string& _name = std::string()) 
deba@1901:       : Parent(_writer), name(_name) {}
deba@1409: 
deba@1409:     /// \brief Destructor.
deba@1409:     ///
deba@1409:     /// Destructor for AttributeWriter.
deba@1409:     virtual ~AttributeWriter() {
deba@1409:       typename Writers::iterator it;
deba@1409:       for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409: 	delete it->second;
deba@1409:       }
deba@1409:     }
deba@1409: 
deba@1409:   private:
deba@1409:     AttributeWriter(const AttributeWriter&);
deba@1409:     void operator=(AttributeWriter&);
deba@1409: 
deba@1409:   public:
deba@1409:     /// \brief Add an attribute writer command for the writer.
deba@1409:     ///
deba@1409:     /// Add an attribute writer command for the writer.
deba@1409:     template <typename Value>
deba@1901:     AttributeWriter& writeAttribute(const std::string& name, 
deba@1409: 				    const Value& value) {
deba@1409:       return 
deba@1901: 	writeAttribute<typename Traits::template Writer<Value> >(name, value);
deba@1409:     }
deba@1409: 
deba@1409:     /// \brief Add an attribute writer command for the writer.
deba@1409:     ///
deba@1409:     /// Add an attribute writer command for the writer.
deba@1409:     template <typename Writer, typename Value>
deba@1409:     AttributeWriter& writeAttribute(const std::string& name, 
deba@1409: 				    const Value& value,
deba@1409: 				    const Writer& writer = Writer()) {
deba@1492:       checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
deba@1845:       writers.push_back(make_pair(name, new _writer_bits::
deba@1845: 				  ValueWriter<Value, Writer>(value, writer)));
deba@1409:       return *this;
deba@1409:     }
deba@1409: 
deba@1409:   protected:
deba@1409: 
deba@1409:     /// \brief The header of section.
deba@1409:     ///
deba@1409:     /// It gives back the header of the section.
deba@1409:     std::string header() {
deba@1901:       return "@attributes " + name;
deba@1409:     }
deba@1409: 
deba@1409:     /// \brief  Writer function of the section.
deba@1409:     ///
deba@1409:     /// Write the content of the section.
deba@1409:     void write(std::ostream& os) {
deba@1409:       typename Writers::iterator it;
deba@1409:       for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409: 	os << it->first << ' ';
deba@1409: 	it->second->write(os);
deba@1409: 	os << std::endl;
deba@1409:       }
deba@1409:     }    
deba@1409: 
deba@1409:   private:
deba@1901:     std::string name;
deba@1409: 
deba@1845:     typedef std::vector<std::pair<std::string, 
deba@1845: 				  _writer_bits::ValueWriterBase*> > Writers;
deba@1409:     Writers writers;  
deba@1409:   };
deba@1409: 
deba@1409: 
deba@1409: }
deba@1409: #endif