lemon/lemon_writer.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2101 439b7f21ccc4
child 2260 4274224f8a7d
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
deba@1409
     1
/* -*- C++ -*-
deba@1409
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1409
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1409
     8
 *
deba@1409
     9
 * Permission to use, modify and distribute this software is granted
deba@1409
    10
 * provided that this copyright notice appears in all copies. For
deba@1409
    11
 * precise terms see the accompanying LICENSE file.
deba@1409
    12
 *
deba@1409
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@1409
    14
 * express or implied, and with no claim as to its suitability for any
deba@1409
    15
 * purpose.
deba@1409
    16
 *
deba@1409
    17
 */
deba@1409
    18
deba@2084
    19
///\ingroup lemon_io
deba@1409
    20
///\file
deba@1409
    21
///\brief Lemon Format writer.
deba@1409
    22
deba@1409
    23
#ifndef LEMON_LEMON_WRITER_H
deba@1409
    24
#define LEMON_LEMON_WRITER_H
deba@1409
    25
deba@1409
    26
#include <iostream>
deba@1409
    27
#include <fstream>
deba@1409
    28
#include <string>
deba@1409
    29
#include <vector>
deba@1409
    30
#include <algorithm>
deba@1409
    31
#include <map>
deba@1409
    32
#include <memory>
deba@1409
    33
deba@1409
    34
#include <lemon/error.h>
deba@1993
    35
#include <lemon/bits/invalid.h>
deba@1421
    36
#include <lemon/graph_utils.h>
deba@1409
    37
#include <lemon/bits/item_writer.h>
deba@1993
    38
#include <lemon/bits/utility.h>
deba@1421
    39
#include <lemon/maps.h>
alpar@2207
    40
#include <lemon/dim2.h>
deba@1409
    41
deba@1476
    42
#include <lemon/concept_check.h>
deba@1476
    43
#include <lemon/concept/maps.h>
deba@1476
    44
deba@1409
    45
deba@1409
    46
namespace lemon {
deba@1409
    47
deba@1476
    48
  namespace _writer_bits {
deba@1476
    49
    
deba@2101
    50
    template <typename T>
deba@2101
    51
    bool operator<(T, T) {
deba@2101
    52
      throw DataFormatError("Label is not comparable");
deba@2101
    53
    }
deba@2101
    54
deba@2101
    55
    template <typename T>
deba@2101
    56
    struct Less {
deba@2101
    57
      bool operator()(const T& p, const T& q) const {
deba@2101
    58
	return p < q;
deba@2101
    59
      }
deba@2101
    60
    };
deba@2101
    61
deba@2101
    62
    template <typename Map>
deba@2101
    63
    struct ComposeLess {
deba@2101
    64
      ComposeLess(const Map& _map) : map(_map), less() {}
deba@2101
    65
deba@2101
    66
      bool operator()(const typename Map::Key& p, 
deba@2101
    67
                      const typename Map::Key& q) const {
deba@2101
    68
	return less(map[p], map[q]);
deba@2101
    69
      }
deba@2101
    70
      const Map& map;
deba@2101
    71
      Less<typename Map::Value> less;
deba@2101
    72
    };
deba@2101
    73
deba@1476
    74
    template <typename Item>
deba@1901
    75
    class ItemLabelWriter {
deba@1476
    76
    public:
deba@1476
    77
deba@1901
    78
      bool isLabelWriter() { return true; }
deba@1476
    79
deba@1901
    80
      void writeLabel(std::ostream&, const Item&) {}
deba@1476
    81
      
deba@1901
    82
      template <class _ItemLabelWriter>
deba@1476
    83
      struct Constraints {
deba@1476
    84
	void constraints() {
deba@1901
    85
	  bool b = writer.isLabelWriter();
deba@1476
    86
	  ignore_unused_variable_warning(b);
deba@1901
    87
	  writer.writeLabel(os, item);
deba@1476
    88
	}
deba@1901
    89
	_ItemLabelWriter& writer;
deba@1476
    90
	std::ostream& os;
deba@1492
    91
	const Item& item;
deba@1492
    92
      };
deba@1492
    93
deba@1492
    94
    };
deba@1492
    95
deba@1492
    96
    template <typename Item>
deba@1492
    97
    class ItemWriter {
deba@1492
    98
    public:
deba@1492
    99
deba@1492
   100
      void write(std::ostream&, const Item&) {}
deba@1492
   101
      
deba@1492
   102
      template <class _ItemWriter>
deba@1492
   103
      struct Constraints {
deba@1492
   104
	void constraints() {
deba@1492
   105
	  writer.write(os, item);
deba@1492
   106
	}
deba@1492
   107
	_ItemWriter& writer;
deba@1492
   108
	std::ostream& os;
deba@1492
   109
	const Item& item;
deba@1476
   110
      };
deba@1476
   111
deba@1476
   112
    };
deba@1476
   113
deba@1705
   114
    template <typename Map>
deba@1705
   115
    struct Ref { typedef const Map& Type; };
deba@1705
   116
deba@1705
   117
    template <typename Graph, typename Map>
deba@1705
   118
    class ForwardComposeMap {
deba@1705
   119
    public:
klao@1909
   120
      typedef typename Graph::UEdge Key;
deba@1705
   121
      typedef typename Map::Value Value;
deba@1705
   122
deba@1705
   123
      ForwardComposeMap(const Graph& _graph, const Map& _map) 
deba@1705
   124
	: graph(_graph), map(_map) {}
deba@1705
   125
      
deba@1705
   126
      Value operator[](const Key& key) {
deba@1705
   127
	return map[graph.direct(key, false)];
deba@1705
   128
      }
deba@1705
   129
deba@1705
   130
    private:
deba@1705
   131
      typename Ref<Map>::Type map;
deba@1705
   132
      const Graph& graph;
deba@1705
   133
    };
deba@1705
   134
deba@1705
   135
    template <typename Graph, typename Map>
deba@1705
   136
    ForwardComposeMap<Graph, Map>
deba@1705
   137
    forwardComposeMap(const Graph& graph, const Map& map) {
deba@1705
   138
      return ForwardComposeMap<Graph, Map>(graph, map);
deba@1705
   139
    }
deba@1705
   140
deba@1705
   141
    template <typename Graph, typename Map>
deba@1705
   142
    class BackwardComposeMap {
deba@1705
   143
    public:
klao@1909
   144
      typedef typename Graph::UEdge Key;
deba@1705
   145
      typedef typename Map::Value Value;
deba@1705
   146
deba@1705
   147
      BackwardComposeMap(const Graph& _graph, const Map& _map) 
deba@1705
   148
	: graph(_graph), map(_map) {}
deba@1705
   149
      
deba@1705
   150
      Value operator[](const Key& key) {
deba@1705
   151
	return map[graph.direct(key, false)];
deba@1705
   152
      }
deba@1705
   153
deba@1705
   154
    private:
deba@1705
   155
      typename Ref<Map>::Type map;
deba@1705
   156
      const Graph& graph;
deba@1705
   157
    };
deba@1705
   158
deba@1705
   159
    template <typename Graph, typename Map>
deba@1705
   160
    BackwardComposeMap<Graph, Map>
deba@1705
   161
    backwardComposeMap(const Graph& graph, const Map& map) {
deba@1705
   162
      return BackwardComposeMap<Graph, Map>(graph, map);
deba@1705
   163
    }
deba@1705
   164
deba@1705
   165
    template <typename Graph, typename Map>
deba@1705
   166
    struct Ref<ForwardComposeMap<Graph, Map> > { 
deba@1705
   167
      typedef ForwardComposeMap<Graph, Map> Type;
deba@1705
   168
    };
deba@1705
   169
deba@1705
   170
    template <typename Graph, typename Map>
deba@1705
   171
    struct Ref<BackwardComposeMap<Graph, Map> > { 
deba@1705
   172
      typedef BackwardComposeMap<Graph, Map> Type; 
deba@1705
   173
    };
deba@1705
   174
deba@1705
   175
    template <typename Map>
alpar@2207
   176
    struct Ref<dim2::XMap<Map> > { 
alpar@2207
   177
      typedef dim2::XMap<Map> Type;
deba@1705
   178
    };
deba@1705
   179
    template <typename Map>
alpar@2207
   180
    struct Ref<dim2::ConstXMap<Map> > { 
alpar@2207
   181
      typedef dim2::ConstXMap<Map> Type;
deba@1705
   182
    };
deba@1705
   183
deba@1705
   184
    template <typename Map>
alpar@2207
   185
    struct Ref<dim2::YMap<Map> > { 
alpar@2207
   186
      typedef dim2::YMap<Map> Type;
deba@1705
   187
    };
deba@1705
   188
    template <typename Map>
alpar@2207
   189
    struct Ref<dim2::ConstYMap<Map> > { 
alpar@2207
   190
      typedef dim2::ConstYMap<Map> Type;
deba@1705
   191
    };
deba@1705
   192
deba@1845
   193
deba@1845
   194
    template <typename _Item>    
deba@1845
   195
    class MapWriterBase {
deba@1845
   196
    public:
deba@1845
   197
      typedef _Item Item;
deba@1845
   198
deba@1845
   199
      virtual ~MapWriterBase() {}
deba@1845
   200
deba@1852
   201
      virtual void write(std::ostream& os, const Item& item) const = 0;
deba@2101
   202
      virtual void sortByMap(std::vector<Item>&) const = 0;
deba@1845
   203
    };
deba@1845
   204
deba@1845
   205
deba@1845
   206
    template <typename _Item, typename _Map, typename _Writer>
deba@1845
   207
    class MapWriter : public MapWriterBase<_Item> {
deba@1845
   208
    public:
deba@1845
   209
      typedef _Map Map;
deba@1845
   210
      typedef _Writer Writer;
deba@1845
   211
      typedef typename Writer::Value Value;
deba@1845
   212
      typedef _Item Item;
deba@1845
   213
      
deba@1845
   214
      typename _writer_bits::Ref<Map>::Type map;
deba@1845
   215
      Writer writer;
deba@1845
   216
deba@1845
   217
      MapWriter(const Map& _map, const Writer& _writer) 
deba@1845
   218
	: map(_map), writer(_writer) {}
deba@1845
   219
deba@1845
   220
      virtual ~MapWriter() {}
deba@1845
   221
deba@1852
   222
      virtual void write(std::ostream& os, const Item& item) const {
deba@1845
   223
	Value value = map[item];
deba@1845
   224
	writer.write(os, value);
deba@1845
   225
      }
deba@1845
   226
deba@2101
   227
      virtual void sortByMap(std::vector<Item>& items) const {
deba@2101
   228
        ComposeLess<Map> less(map);
deba@2101
   229
        std::sort(items.begin(), items.end(), less);
deba@2101
   230
      }
deba@2101
   231
deba@1845
   232
    };
deba@1845
   233
deba@1845
   234
deba@1845
   235
    class ValueWriterBase {
deba@1845
   236
    public:
deba@1845
   237
      virtual ~ValueWriterBase() {}
deba@1845
   238
      virtual void write(std::ostream&) = 0;
deba@1845
   239
    };
deba@1845
   240
deba@1845
   241
    template <typename _Value, typename _Writer>
deba@1845
   242
    class ValueWriter : public ValueWriterBase {
deba@1845
   243
    public:
deba@1845
   244
      typedef _Value Value;
deba@1845
   245
      typedef _Writer Writer;
deba@1845
   246
deba@1845
   247
      ValueWriter(const Value& _value, const Writer& _writer)
deba@1845
   248
 	: value(_value), writer(_writer) {}
deba@1845
   249
deba@1845
   250
      virtual void write(std::ostream& os) {
deba@1845
   251
	writer.write(os, value);
deba@1845
   252
      }
deba@1845
   253
    private:
deba@1845
   254
      const Value& value;
deba@1845
   255
      Writer writer;
deba@1845
   256
    };
deba@1845
   257
    
deba@1845
   258
deba@1845
   259
    template <typename _Item>
deba@1901
   260
    class LabelWriterBase {
deba@1845
   261
    public:
deba@1845
   262
      typedef _Item Item;
deba@1901
   263
      virtual ~LabelWriterBase() {}
deba@1845
   264
      virtual void write(std::ostream&, const Item&) const = 0;
deba@1901
   265
      virtual bool isLabelWriter() const = 0;
deba@1845
   266
    };
deba@1845
   267
deba@1901
   268
    template <typename _Item, typename _BoxedLabelWriter>
deba@1901
   269
    class LabelWriter : public LabelWriterBase<_Item> {
deba@1845
   270
    public:
deba@1845
   271
      typedef _Item Item;
deba@1901
   272
      typedef _BoxedLabelWriter BoxedLabelWriter;
deba@1845
   273
deba@1901
   274
      const BoxedLabelWriter& labelWriter;
deba@1845
   275
deba@1901
   276
      LabelWriter(const BoxedLabelWriter& _labelWriter) 
deba@1901
   277
	: labelWriter(_labelWriter) {}
deba@1845
   278
deba@1845
   279
      virtual void write(std::ostream& os, const Item& item) const {
deba@1901
   280
	labelWriter.writeLabel(os, item);
deba@1845
   281
      }
deba@1845
   282
deba@1901
   283
      virtual bool isLabelWriter() const {
deba@1901
   284
	return labelWriter.isLabelWriter();
deba@1845
   285
      }
deba@1845
   286
    };
deba@1845
   287
deba@1476
   288
  }
deba@1476
   289
deba@2084
   290
  /// \ingroup lemon_io
deba@1409
   291
  /// \brief Lemon Format writer class.
deba@1409
   292
  /// 
deba@1409
   293
  /// The Lemon Format contains several sections. We do not want to
deba@1409
   294
  /// determine what sections are in a lemon file we give only a framework
deba@1409
   295
  /// to write a section oriented format.
deba@1409
   296
  ///
deba@1409
   297
  /// In the Lemon Format each section starts with a line contains a \c \@
deba@1409
   298
  /// character on the first not white space position. This line is the
deba@1409
   299
  /// header line of the section. Each next lines belong to this section
deba@1409
   300
  /// while it does not starts with \c \@ character. This line can start a 
deba@1409
   301
  /// new section or if it can close the file with the \c \@end line.
deba@1409
   302
  /// The file format ignore the empty lines and it may contain comments
deba@1409
   303
  /// started with a \c # character to the end of the line. 
deba@1409
   304
  ///
deba@1409
   305
  /// The framework provides an abstract LemonWriter::SectionWriter class
deba@1409
   306
  /// what defines the interface of a SectionWriter. The SectionWriter
deba@1409
   307
  /// has the \c header() member function what gives back the header of the
deba@1409
   308
  /// section. After that it will be called the \c write() member which
deba@1409
   309
  /// should write the content of the section.
deba@1409
   310
  ///
deba@1409
   311
  /// \relates GraphWriter
deba@1409
   312
  /// \relates NodeSetWriter
deba@1409
   313
  /// \relates EdgeSetWriter
deba@1409
   314
  /// \relates NodesWriter
deba@1409
   315
  /// \relates EdgesWriter
deba@1409
   316
  /// \relates AttributeWriter
deba@1409
   317
  class LemonWriter {
deba@1409
   318
  public:
deba@1409
   319
deba@1409
   320
    /// \brief Abstract base class for writing a section.
deba@1409
   321
    ///
deba@1409
   322
    /// This class has an \c header() member function what gives back
deba@1409
   323
    /// the header line of the section. The \c write() member should
deba@1409
   324
    /// write the content of the section to the stream.
deba@1409
   325
    class SectionWriter {
deba@1409
   326
      friend class LemonWriter;
deba@1409
   327
    protected:
deba@1409
   328
      /// \brief Constructor for SectionWriter.
deba@1409
   329
      ///
deba@1409
   330
      /// Constructor for SectionWriter. It attach this writer to
deba@1409
   331
      /// the given LemonWriter.
deba@1409
   332
      SectionWriter(LemonWriter& writer) {
deba@1409
   333
	writer.attach(*this);
deba@1409
   334
      }
alpar@1494
   335
      
alpar@1494
   336
      virtual ~SectionWriter() {}
deba@1409
   337
deba@1409
   338
      /// \brief The header of section.
deba@1409
   339
      ///
deba@1409
   340
      /// It gives back the header of the section.
deba@1409
   341
      virtual std::string header() = 0;
deba@1409
   342
deba@2084
   343
      /// \brief Writer function of the section.
deba@1409
   344
      ///
deba@1409
   345
      /// Write the content of the section.
deba@1409
   346
      virtual void write(std::ostream& os) = 0;
deba@2084
   347
      
deba@2084
   348
      /// \brief Gives back true when the section should be written.
deba@2084
   349
      ///
deba@2084
   350
      /// Gives back true when the section should be written.
deba@2084
   351
      virtual bool valid() { return true; }
deba@1409
   352
    };
deba@1409
   353
deba@1409
   354
    /// \brief Constructor for LemonWriter.
deba@1409
   355
    ///
deba@1409
   356
    /// Constructor for LemonWriter which writes to the given stream.
deba@1409
   357
    LemonWriter(std::ostream& _os) 
deba@1409
   358
      : os(&_os), own_os(false) {}
deba@1409
   359
deba@1409
   360
    /// \brief Constructor for LemonWriter.
deba@1409
   361
    ///
deba@1409
   362
    /// Constructor for LemonWriter which writes to the given file.
deba@1409
   363
    LemonWriter(const std::string& filename) 
deba@1409
   364
      : os(0), own_os(true) {
deba@1409
   365
      os = new std::ofstream(filename.c_str());
deba@1409
   366
    }
deba@1409
   367
deba@1409
   368
    /// \brief Desctructor for LemonWriter.
deba@1409
   369
    ///
deba@1409
   370
    /// Desctructor for LemonWriter.
deba@1409
   371
    ~LemonWriter() {
deba@1409
   372
      if (own_os) {
deba@1409
   373
	delete os;
deba@1409
   374
      }
deba@1409
   375
    }
deba@1409
   376
deba@1409
   377
  private:
deba@1409
   378
    LemonWriter(const LemonWriter&);
deba@1409
   379
    void operator=(const LemonWriter&);
deba@1409
   380
deba@1409
   381
    void attach(SectionWriter& writer) {
deba@1409
   382
      writers.push_back(&writer);
deba@1409
   383
    }
deba@1409
   384
deba@1409
   385
  public:
deba@1409
   386
deba@1409
   387
    /// \brief Executes the LemonWriter.
deba@1409
   388
    /// 
deba@1409
   389
    /// It executes the LemonWriter.
deba@1409
   390
    void run() {
deba@1409
   391
      SectionWriters::iterator it;
deba@1409
   392
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@2084
   393
        if ((*it)->valid()) {
deba@2084
   394
          *os << (*it)->header() << std::endl;
deba@2084
   395
          (*it)->write(*os);
deba@2084
   396
        }
deba@1409
   397
      }
deba@1409
   398
      *os << "@end" << std::endl;
deba@1409
   399
    }
deba@1409
   400
deba@1409
   401
deba@1409
   402
  private:
deba@1409
   403
deba@1409
   404
    std::ostream* os;
deba@1409
   405
    bool own_os;
deba@1409
   406
deba@1409
   407
    typedef std::vector<SectionWriter*> SectionWriters;
deba@1409
   408
    SectionWriters writers;
deba@1409
   409
deba@1409
   410
  };
deba@1409
   411
deba@2016
   412
  /// \ingroup section_io
deba@1409
   413
  /// \brief SectionWriter for writing a graph's nodeset.
deba@1409
   414
  ///
deba@1409
   415
  /// The lemon format can store multiple graph nodesets with several maps.
deba@1901
   416
  /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but 
deba@1901
   417
  /// the \c nodeset_name may be empty.
deba@1409
   418
  ///
deba@1409
   419
  /// The first line of the section contains the names of the maps separated
deba@1409
   420
  /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409
   421
  /// contains the mapped values for each map.
deba@1409
   422
  ///
deba@1901
   423
  /// If the nodeset contains an \c "label" named map then it will be regarded
deba@1901
   424
  /// as label map. This map should contain only unique values and when the 
deba@1901
   425
  /// \c writeLabel() member will be called with a node it will write it's 
deba@1901
   426
  /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
deba@2101
   427
  /// then the label map will be the id in the graph. In addition if the
deba@2101
   428
  /// the \c _sortByLabel is true then the writer will write the edges
deba@2101
   429
  /// sorted by the labels.
deba@1409
   430
  ///
deba@1409
   431
  /// \relates LemonWriter
deba@1409
   432
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1845
   433
  class NodeSetWriter : public LemonWriter::SectionWriter {
deba@1845
   434
    typedef LemonWriter::SectionWriter Parent;
deba@1409
   435
  public:
deba@1409
   436
deba@1409
   437
    typedef _Graph Graph;
deba@1409
   438
    typedef _Traits Traits;
deba@1429
   439
    typedef typename Graph::Node Node;
deba@1409
   440
deba@1409
   441
    /// \brief Constructor.
deba@1409
   442
    ///
deba@1409
   443
    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
deba@1901
   444
    /// attach it into the given LemonWriter. If the \c _forceLabelMap
deba@1901
   445
    /// parameter is true then the writer will write own label map when
deba@2101
   446
    /// the user does not give "label" named map. In addition if the
deba@2101
   447
    /// the \c _sortByLabel is true then the writer will write the edges
deba@2101
   448
    /// sorted by the labels.
deba@1409
   449
    NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1901
   450
		  const std::string& _name = std::string(), 
deba@2101
   451
		  bool _forceLabelMap = true, bool _sortByLabel = true) 
deba@1901
   452
      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), 
deba@2101
   453
	sortByLabel(_sortByLabel), graph(_graph), name(_name) {}
deba@1409
   454
deba@1409
   455
    /// \brief Destructor.
deba@1409
   456
    ///
deba@1409
   457
    /// Destructor for NodeSetWriter.
deba@1409
   458
    virtual ~NodeSetWriter() {
deba@1409
   459
      typename MapWriters::iterator it;
deba@1409
   460
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   461
	delete it->second;
deba@1409
   462
      }
deba@1409
   463
    }
deba@1409
   464
deba@1409
   465
  private:
deba@1409
   466
    NodeSetWriter(const NodeSetWriter&);
deba@1409
   467
    void operator=(const NodeSetWriter&);
deba@1409
   468
  
deba@1409
   469
  public:
deba@1409
   470
deba@1409
   471
    /// \brief Add a new node map writer command for the writer.
deba@1409
   472
    ///
deba@1409
   473
    /// Add a new node map writer command for the writer.
deba@1409
   474
    template <typename Map>
deba@1421
   475
    NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
deba@1421
   476
      return writeNodeMap<typename Traits::
deba@1409
   477
	template Writer<typename Map::Value>, Map>(name, map);
deba@1409
   478
    }
deba@1409
   479
deba@1409
   480
    /// \brief Add a new node map writer command for the writer.
deba@1409
   481
    ///
deba@1409
   482
    /// Add a new node map writer command for the writer.
deba@1409
   483
    template <typename Writer, typename Map>
deba@1421
   484
    NodeSetWriter& writeNodeMap(std::string name, const Map& map, 
deba@1421
   485
			    const Writer& writer = Writer()) {
deba@1492
   486
      checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
deba@1492
   487
      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@1409
   488
      writers.push_back(
deba@1845
   489
	make_pair(name, new _writer_bits::
deba@1845
   490
		  MapWriter<Node, Map, Writer>(map, writer)));
deba@1409
   491
      return *this;
deba@1409
   492
    }
deba@1409
   493
deba@1409
   494
  protected:
deba@1409
   495
deba@1409
   496
    /// \brief The header of the section.
deba@1409
   497
    ///
deba@1409
   498
    /// It gives back the header of the section.
deba@1409
   499
    virtual std::string header() {
deba@1901
   500
      return "@nodeset " + name;
deba@1409
   501
    }
deba@1409
   502
deba@1409
   503
    /// \brief  Writer function of the section.
deba@1409
   504
    ///
deba@1409
   505
    /// Write the content of the section.
deba@1409
   506
    virtual void write(std::ostream& os) {
deba@1409
   507
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@2084
   508
	if (writers[i].first == "label") {
deba@1901
   509
	  labelMap = writers[i].second;
deba@1901
   510
	  forceLabelMap = false;
deba@1409
   511
	  break;
deba@1409
   512
	}
deba@1409
   513
      }
deba@2101
   514
      std::vector<Node> items;
deba@2101
   515
      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
deba@2101
   516
        items.push_back(it);
deba@2101
   517
      }
deba@2101
   518
      if (sortByLabel) {
deba@2101
   519
        if (labelMap) {
deba@2101
   520
          labelMap->sortByMap(items);
deba@2101
   521
        } else {
deba@2101
   522
          typedef IdMap<Graph, Node> Map;
deba@2101
   523
          Map map(graph);
deba@2101
   524
          _writer_bits::ComposeLess<Map> less(map);
deba@2101
   525
          std::sort(items.begin(), items.end(), less);
deba@2101
   526
        }
deba@2101
   527
      }
deba@1901
   528
      if (forceLabelMap) {
deba@1901
   529
	os << "label\t";
deba@1409
   530
      }
deba@1409
   531
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   532
	os << writers[i].first << '\t';
deba@1409
   533
      }
deba@1409
   534
      os << std::endl;
deba@2101
   535
      for (typename std::vector<Node>::iterator it = items.begin();
deba@2101
   536
           it != items.end(); ++it) {
deba@1901
   537
	if (forceLabelMap) {
deba@2101
   538
	  os << graph.id(*it) << '\t';
deba@1409
   539
	}
deba@1409
   540
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@2101
   541
	  writers[i].second->write(os, *it);
deba@1409
   542
	  os << '\t';
deba@1409
   543
	}
deba@1409
   544
	os << std::endl;
deba@1409
   545
      }
deba@1409
   546
    }
deba@1409
   547
deba@1409
   548
  public:
deba@1409
   549
deba@1901
   550
    /// \brief Returns true if the nodeset can write the labels of the nodes.
deba@1409
   551
    ///
deba@1901
   552
    /// Returns true if the nodeset can write the labels of the nodes.
deba@1901
   553
    /// It is possible only if an "label" named map was written or the 
deba@1901
   554
    /// \c _forceLabelMap constructor parameter was true.
deba@1901
   555
    bool isLabelWriter() const {
deba@1901
   556
      return labelMap != 0 || forceLabelMap;
deba@1409
   557
    }
deba@1409
   558
deba@1901
   559
    /// \brief Write the label of the given node.
deba@1409
   560
    ///
deba@1901
   561
    /// It writes the label of the given node. If there was written an "label"
deba@1409
   562
    /// named map then it will write the map value belongs to the node.
deba@1901
   563
    /// Otherwise if the \c forceLabel parameter was true it will write
deba@1901
   564
    /// its label in the graph. 
deba@1901
   565
    void writeLabel(std::ostream& os, const Node& item) const {
deba@1901
   566
      if (forceLabelMap) {
deba@1409
   567
	os << graph.id(item);
deba@1409
   568
      } else {
deba@1901
   569
	labelMap->write(os, item);
deba@1409
   570
      }
deba@1409
   571
    }
deba@1409
   572
deba@1409
   573
  private:
deba@1409
   574
deba@1845
   575
    typedef std::vector<std::pair<std::string, _writer_bits::
deba@1845
   576
				  MapWriterBase<Node>*> > MapWriters;
deba@1409
   577
    MapWriters writers;
deba@1409
   578
deba@1901
   579
    _writer_bits::MapWriterBase<Node>* labelMap;
deba@1901
   580
    bool forceLabelMap;
deba@2101
   581
    bool sortByLabel;
deba@1409
   582
   
deba@1705
   583
    const Graph& graph;   
deba@1901
   584
    std::string name;
deba@1409
   585
deba@1409
   586
  };
deba@1409
   587
deba@2016
   588
  /// \ingroup section_io
deba@1421
   589
  /// \brief SectionWriter for writing a graph's edgesets.
deba@1409
   590
  ///
deba@1421
   591
  /// The lemon format can store multiple graph edgesets with several maps. 
deba@1901
   592
  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but 
deba@1901
   593
  /// the \c edgeset_name may be empty.
deba@1409
   594
  ///
deba@1409
   595
  /// The first line of the section contains the names of the maps separated
deba@1409
   596
  /// with white spaces. Each next lines describes a edge in the edgeset. The
deba@1901
   597
  /// line contains the source and the target nodes' label and the mapped 
deba@1409
   598
  /// values for each map.
deba@1409
   599
  ///
deba@1901
   600
  /// If the edgeset contains an \c "label" named map then it will be regarded
deba@1901
   601
  /// as label map. This map should contain only unique values and when the 
deba@1901
   602
  /// \c writeLabel() member will be called with an edge it will write it's 
deba@1901
   603
  /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
deba@2101
   604
  /// then the label map will be the id in the graph. In addition if the
deba@2101
   605
  /// the \c _sortByLabel is true then the writer will write the edges
deba@2101
   606
  /// sorted by the labels.
deba@1409
   607
  ///
deba@1901
   608
  /// The edgeset writer needs a node label writer to identify which nodes
deba@1901
   609
  /// have to be connected. If a NodeSetWriter can write the nodes' label,
deba@1409
   610
  /// it will be able to use with this class.
deba@1409
   611
  ///
deba@1409
   612
  /// \relates LemonWriter
deba@1409
   613
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1845
   614
  class EdgeSetWriter : public LemonWriter::SectionWriter {
deba@1845
   615
    typedef LemonWriter::SectionWriter Parent;
deba@1409
   616
  public:
deba@1409
   617
deba@1409
   618
    typedef _Graph Graph;
deba@1409
   619
    typedef _Traits Traits;
deba@1429
   620
    typedef typename Graph::Node Node;
deba@1429
   621
    typedef typename Graph::Edge Edge;
deba@1409
   622
deba@1409
   623
    /// \brief Constructor.
deba@1409
   624
    ///
deba@2101
   625
    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter
deba@2101
   626
    /// and attach it into the given LemonWriter. It will write node
deba@2101
   627
    /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
deba@2101
   628
    /// parameter is true then the writer will write own label map if
deba@2101
   629
    /// the user does not give "label" named map. In addition if the
deba@2101
   630
    /// the \c _sortByLabel is true then the writer will write the
deba@2101
   631
    /// edges sorted by the labels.
deba@1901
   632
    template <typename NodeLabelWriter>
deba@1409
   633
    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1901
   634
		  const NodeLabelWriter& _nodeLabelWriter, 
deba@1901
   635
		  const std::string& _name = std::string(),
deba@2101
   636
		  bool _forceLabelMap = true, bool _sortByLabel = true)
deba@1901
   637
      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
deba@2101
   638
	sortByLabel(_sortByLabel), graph(_graph), name(_name) {
deba@1901
   639
      checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
deba@1901
   640
      nodeLabelWriter.reset(new _writer_bits::
deba@1901
   641
			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
deba@1476
   642
    } 
deba@1409
   643
deba@1409
   644
    /// \brief Destructor.
deba@1409
   645
    ///
deba@1409
   646
    /// Destructor for EdgeSetWriter.
deba@1409
   647
    virtual ~EdgeSetWriter() {
deba@1409
   648
      typename MapWriters::iterator it;
deba@1409
   649
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   650
	delete it->second;
deba@1409
   651
      }
deba@1409
   652
    }
deba@1409
   653
deba@1409
   654
  private:
deba@1409
   655
    EdgeSetWriter(const EdgeSetWriter&);
deba@1409
   656
    void operator=(const EdgeSetWriter&);
deba@1409
   657
deba@1409
   658
  public:
deba@1409
   659
deba@1421
   660
    /// \brief Add a new edge map writer command for the writer.
deba@1409
   661
    ///
deba@1421
   662
    /// Add a new edge map writer command for the writer.
deba@1409
   663
    template <typename Map>
deba@1421
   664
    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
deba@1421
   665
      return writeEdgeMap<typename Traits::
deba@1409
   666
	template Writer<typename Map::Value>, Map>(name, map);
deba@1409
   667
    }
deba@1409
   668
deba@1421
   669
    /// \brief Add a new edge map writer command for the writer.
deba@1409
   670
    ///
deba@1421
   671
    /// Add a new edge map writer command for the writer.
deba@1409
   672
    template <typename Writer, typename Map>
deba@1421
   673
    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
deba@1421
   674
			    const Writer& writer = Writer()) {
deba@1492
   675
      checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
deba@1492
   676
      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@1409
   677
      writers.push_back(
deba@1845
   678
	make_pair(name, new _writer_bits::
deba@1845
   679
		  MapWriter<Edge, Map, Writer>(map, writer)));
deba@1409
   680
      return *this;
deba@1409
   681
    }
deba@1409
   682
deba@1409
   683
  protected:
deba@1409
   684
deba@1409
   685
    /// \brief The header of the section.
deba@1409
   686
    ///
deba@1409
   687
    /// It gives back the header of the section.
deba@1409
   688
    virtual std::string header() {
deba@1901
   689
      return "@edgeset " + name;
deba@1409
   690
    }
deba@1409
   691
deba@1409
   692
    /// \brief  Writer function of the section.
deba@1409
   693
    ///
deba@1409
   694
    /// Write the content of the section.
deba@1409
   695
    virtual void write(std::ostream& os) {
deba@1901
   696
      if (!nodeLabelWriter->isLabelWriter()) {
deba@1901
   697
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
   698
      }
deba@1409
   699
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@2084
   700
	if (writers[i].first == "label") {
deba@1901
   701
	  labelMap = writers[i].second;
deba@1901
   702
	  forceLabelMap = false;
deba@1409
   703
	  break;
deba@1409
   704
	}
deba@1409
   705
      }
deba@2101
   706
      std::vector<Edge> items;
deba@2101
   707
      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
deba@2101
   708
        items.push_back(it);
deba@2101
   709
      }
deba@2101
   710
      if (sortByLabel) {
deba@2101
   711
        if (labelMap) {
deba@2101
   712
          labelMap->sortByMap(items);
deba@2101
   713
        } else {
deba@2101
   714
          typedef IdMap<Graph, Edge> Map;
deba@2101
   715
          Map map(graph);
deba@2101
   716
          _writer_bits::ComposeLess<Map> less(map);
deba@2101
   717
          std::sort(items.begin(), items.end(), less);
deba@2101
   718
        }
deba@2101
   719
      }
deba@1409
   720
      os << "\t\t";
deba@1901
   721
      if (forceLabelMap) {
deba@1901
   722
	os << "label\t";
deba@1409
   723
      }
deba@1409
   724
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   725
	os << writers[i].first << '\t';
deba@1409
   726
      }
deba@1409
   727
      os << std::endl;
deba@2101
   728
      for (typename std::vector<Edge>::iterator it = items.begin();
deba@2101
   729
           it != items.end(); ++it) {
deba@2101
   730
	nodeLabelWriter->write(os, graph.source(*it));
deba@1409
   731
	os << '\t';
deba@2101
   732
	nodeLabelWriter->write(os, graph.target(*it));
deba@1409
   733
	os << '\t';
deba@1901
   734
	if (forceLabelMap) {
deba@2101
   735
	  os << graph.id(*it) << '\t';
deba@1409
   736
	}
deba@1409
   737
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@2101
   738
	  writers[i].second->write(os, *it);
deba@1409
   739
	  os << '\t';
deba@1409
   740
	}
deba@1409
   741
	os << std::endl;
deba@1409
   742
      }
deba@1409
   743
    }
deba@1409
   744
deba@1409
   745
  public:
deba@1409
   746
deba@1901
   747
    /// \brief Returns true if the edgeset can write the labels of the edges.
deba@1409
   748
    ///
deba@1901
   749
    /// Returns true if the edgeset can write the labels of the edges.
deba@1901
   750
    /// It is possible only if an "label" named map was written or the 
deba@1901
   751
    /// \c _forceLabelMap constructor parameter was true.
deba@1901
   752
    bool isLabelWriter() const {
deba@1901
   753
      return forceLabelMap || labelMap != 0;
deba@1409
   754
    }
deba@1409
   755
deba@1901
   756
    /// \brief Write the label of the given edge.
deba@1409
   757
    ///
deba@1901
   758
    /// It writes the label of the given edge. If there was written an "label"
deba@1409
   759
    /// named map then it will write the map value belongs to the edge.
deba@1901
   760
    /// Otherwise if the \c forceLabel parameter was true it will write
deba@1901
   761
    /// its label in the graph. 
deba@1901
   762
    void writeLabel(std::ostream& os, const Edge& item) const {
deba@1901
   763
      if (forceLabelMap) {
deba@1409
   764
	os << graph.id(item);
deba@1409
   765
      } else {
deba@1901
   766
	labelMap->write(os, item);
deba@1409
   767
      }
deba@1409
   768
    } 
deba@1409
   769
deba@1409
   770
  private:
deba@1409
   771
deba@1845
   772
    typedef std::vector<std::pair<std::string, _writer_bits::
deba@1845
   773
				  MapWriterBase<Edge>*> > MapWriters;
deba@1409
   774
    MapWriters writers;
deba@1409
   775
deba@1901
   776
    _writer_bits::MapWriterBase<Edge>* labelMap;
deba@1901
   777
    bool forceLabelMap;
deba@2101
   778
    bool sortByLabel;
deba@1409
   779
   
deba@1705
   780
    const Graph& graph;   
deba@1901
   781
    std::string name;
deba@1421
   782
deba@1901
   783
    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
deba@1421
   784
  };
deba@1421
   785
deba@2016
   786
  /// \ingroup section_io
deba@1421
   787
  /// \brief SectionWriter for writing a undirected edgeset.
deba@1421
   788
  ///
deba@1421
   789
  /// The lemon format can store multiple undirected edgesets with several 
klao@1909
   790
  /// maps. The undirected edgeset section's header line is \c \@uedgeset 
klao@1909
   791
  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
deba@1421
   792
  ///
deba@1421
   793
  /// The first line of the section contains the names of the maps separated
deba@1421
   794
  /// with white spaces. Each next lines describes an undirected edge in the 
deba@1901
   795
  /// edgeset. The line contains the two connected nodes' label and the mapped 
deba@1421
   796
  /// values for each undirected map.
deba@1421
   797
  ///
deba@1421
   798
  /// The section can handle the directed as a syntactical sugar. Two
deba@1421
   799
  /// undirected edge map describes one directed edge map. This two maps
deba@1421
   800
  /// are the forward map and the backward map and the names of this map
deba@1421
   801
  /// is near the same just with a prefix \c '+' or \c '-' character 
deba@1421
   802
  /// difference.
deba@1421
   803
  ///
deba@2101
   804
  /// If the edgeset contains an \c "label" named map then it will be
deba@2101
   805
  /// regarded as label map. This map should contain only unique
deba@2101
   806
  /// values and when the \c writeLabel() member will be called with
deba@2101
   807
  /// an undirected edge it will write it's label. Otherwise if the \c
deba@2101
   808
  /// _forceLabelMap constructor parameter is true then the label map
deba@2101
   809
  /// will be the id in the graph.  In addition if the the \c
deba@2101
   810
  /// _sortByLabel is true then the writer will write the edges sorted
deba@2101
   811
  /// by the labels.
deba@1421
   812
  ///
deba@1901
   813
  /// The undirected edgeset writer needs a node label writer to identify 
deba@1421
   814
  /// which nodes have to be connected. If a NodeSetWriter can write the 
deba@1901
   815
  /// nodes' label, it will be able to use with this class.
deba@1421
   816
  ///
deba@1421
   817
  /// \relates LemonWriter
deba@1421
   818
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
klao@1909
   819
  class UEdgeSetWriter : public LemonWriter::SectionWriter {
deba@1845
   820
    typedef LemonWriter::SectionWriter Parent;
deba@1421
   821
  public:
deba@1421
   822
deba@1421
   823
    typedef _Graph Graph;
deba@1421
   824
    typedef _Traits Traits;
deba@1429
   825
    typedef typename Graph::Node Node;
deba@1429
   826
    typedef typename Graph::Edge Edge;
klao@1909
   827
    typedef typename Graph::UEdge UEdge;
deba@1421
   828
deba@1421
   829
    /// \brief Constructor.
deba@1421
   830
    ///
klao@1909
   831
    /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
deba@2101
   832
    /// and attach it into the given LemonWriter. It will write node
deba@2101
   833
    /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
deba@2101
   834
    /// parameter is true then the writer will write own label map if
deba@2101
   835
    /// the user does not give "label" named map. In addition if the
deba@2101
   836
    /// the \c _sortByLabel is true then the writer will write the
deba@2101
   837
    /// edges sorted by the labels.
deba@1901
   838
    template <typename NodeLabelWriter>
klao@1909
   839
    UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1901
   840
		       const NodeLabelWriter& _nodeLabelWriter, 
deba@1901
   841
		       const std::string& _name = std::string(),
deba@2101
   842
		       bool _forceLabelMap = true, bool _sortByLabel = true)
deba@1901
   843
      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
deba@2101
   844
	sortByLabel(_sortByLabel), graph(_graph), name(_name) {
deba@1901
   845
      checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
deba@1901
   846
      nodeLabelWriter.reset(new _writer_bits::
deba@1901
   847
			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
deba@1476
   848
    } 
deba@1421
   849
deba@1421
   850
    /// \brief Destructor.
deba@1421
   851
    ///
klao@1909
   852
    /// Destructor for UEdgeSetWriter.
klao@1909
   853
    virtual ~UEdgeSetWriter() {
deba@1421
   854
      typename MapWriters::iterator it;
deba@1421
   855
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1421
   856
	delete it->second;
deba@1421
   857
      }
deba@1421
   858
    }
deba@1421
   859
deba@1421
   860
  private:
klao@1909
   861
    UEdgeSetWriter(const UEdgeSetWriter&);
klao@1909
   862
    void operator=(const UEdgeSetWriter&);
deba@1421
   863
deba@1421
   864
  public:
deba@1421
   865
deba@1421
   866
    /// \brief Add a new undirected edge map writer command for the writer.
deba@1421
   867
    ///
deba@1421
   868
    /// Add a new undirected map writer command for the writer.
deba@1421
   869
    template <typename Map>
klao@1909
   870
    UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map) {
klao@1909
   871
      return writeUEdgeMap<typename Traits::
deba@1421
   872
	template Writer<typename Map::Value>, Map>(name, map);
deba@1421
   873
    }
deba@1421
   874
deba@1421
   875
    /// \brief Add a new undirected map writer command for the writer.
deba@1421
   876
    ///
deba@1421
   877
    /// Add a new undirected map writer command for the writer.
deba@1421
   878
    template <typename Writer, typename Map>
klao@1909
   879
    UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map, 
deba@1421
   880
					  const Writer& writer = Writer()) {
klao@1909
   881
      checkConcept<concept::ReadMap<UEdge, typename Map::Value>, Map>();
deba@1492
   882
      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
deba@1421
   883
      writers.push_back(
deba@1845
   884
	make_pair(name, new _writer_bits::
klao@1909
   885
		  MapWriter<UEdge, Map, Writer>(map, writer)));
deba@1421
   886
      return *this;
deba@1421
   887
    }
deba@1421
   888
deba@1421
   889
    /// \brief Add a new directed edge map writer command for the writer.
deba@1421
   890
    ///
deba@1421
   891
    /// Add a new directed map writer command for the writer.
deba@1421
   892
    template <typename Map>
klao@1909
   893
    UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
deba@1492
   894
      return writeEdgeMap<typename Traits::
deba@1492
   895
	template Writer<typename Map::Value>, Map>(name, map);
deba@1421
   896
    }
deba@1421
   897
deba@1421
   898
    /// \brief Add a new directed map writer command for the writer.
deba@1421
   899
    ///
deba@1421
   900
    /// Add a new directed map writer command for the writer.
deba@1421
   901
    template <typename Writer, typename Map>
klao@1909
   902
    UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
deba@1421
   903
				     const Writer& writer = Writer()) {
deba@1492
   904
      checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
deba@1492
   905
      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
klao@1909
   906
      writeUEdge("+" + name, 
deba@1705
   907
		     _writer_bits::forwardComposeMap(graph, map), writer);
klao@1909
   908
      writeUEdge("-" + name, 
deba@1705
   909
		     _writer_bits::backwardComposeMap(graph, map), writer);
deba@1421
   910
      return *this;
deba@1421
   911
    }
deba@1421
   912
deba@1421
   913
  protected:
deba@1421
   914
deba@1421
   915
    /// \brief The header of the section.
deba@1421
   916
    ///
deba@1421
   917
    /// It gives back the header of the section.
deba@1421
   918
    virtual std::string header() {
klao@1909
   919
      return "@uedgeset " + name;
deba@1421
   920
    }
deba@1421
   921
deba@1421
   922
    /// \brief  Writer function of the section.
deba@1421
   923
    ///
deba@1421
   924
    /// Write the content of the section.
deba@1421
   925
    virtual void write(std::ostream& os) {
deba@1901
   926
      if (!nodeLabelWriter->isLabelWriter()) {
deba@1901
   927
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
   928
      }
deba@1421
   929
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1901
   930
	if (writers[i].first == "label") {
deba@1901
   931
	  labelMap = writers[i].second;
deba@1901
   932
	  forceLabelMap = false;
deba@1421
   933
	  break;
deba@1421
   934
	}
deba@1421
   935
      }
deba@2101
   936
      std::vector<UEdge> items;
deba@2101
   937
      for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
deba@2101
   938
        items.push_back(it);
deba@2101
   939
      }
deba@2101
   940
      if (sortByLabel) {
deba@2101
   941
        if (labelMap) {
deba@2101
   942
          labelMap->sortByMap(items);
deba@2101
   943
        } else {
deba@2101
   944
          typedef IdMap<Graph, UEdge> Map;
deba@2101
   945
          Map map(graph);
deba@2101
   946
          _writer_bits::ComposeLess<Map> less(map);
deba@2101
   947
          std::sort(items.begin(), items.end(), less);
deba@2101
   948
        }
deba@2101
   949
      }
deba@1421
   950
      os << "\t\t";
deba@1901
   951
      if (forceLabelMap) {
deba@1901
   952
	os << "label\t";
deba@1421
   953
      }
deba@1421
   954
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421
   955
	os << writers[i].first << '\t';
deba@1421
   956
      }
deba@1421
   957
      os << std::endl;
deba@2101
   958
      for (typename std::vector<Edge>::iterator it = items.begin();
deba@2101
   959
           it != items.end(); ++it) {
deba@2101
   960
	nodeLabelWriter->write(os, graph.source(*it));
deba@1421
   961
	os << '\t';
deba@2101
   962
	nodeLabelWriter->write(os, graph.target(*it));
deba@1421
   963
	os << '\t';
deba@1901
   964
	if (forceLabelMap) {
deba@2101
   965
	  os << graph.id(*it) << '\t';
deba@1421
   966
	}
deba@1421
   967
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@2101
   968
	  writers[i].second->write(os, *it);
deba@1421
   969
	  os << '\t';
deba@1421
   970
	}
deba@1421
   971
	os << std::endl;
deba@1421
   972
      }
deba@1421
   973
    }
deba@1421
   974
deba@1421
   975
  public:
deba@1421
   976
deba@1901
   977
    /// \brief Returns true if the undirected edgeset can write the labels of 
deba@1421
   978
    /// the edges.
deba@1421
   979
    ///
deba@1901
   980
    /// Returns true if the undirected edgeset can write the labels of the 
deba@1901
   981
    /// undirected edges. It is possible only if an "label" named map was 
deba@1901
   982
    /// written or the \c _forceLabelMap constructor parameter was true.
deba@1901
   983
    bool isLabelWriter() const {
deba@1901
   984
      return forceLabelMap || labelMap != 0;
deba@1421
   985
    }
deba@1421
   986
deba@1901
   987
    /// \brief Write the label of the given undirected edge.
deba@1421
   988
    ///
deba@1901
   989
    /// It writes the label of the given undirected edge. If there was written 
deba@1901
   990
    /// an "label" named map then it will write the map value belongs to the 
deba@1901
   991
    /// undirected edge. Otherwise if the \c forceLabel parameter was true it 
deba@1421
   992
    /// will write its id in the graph. 
klao@1909
   993
    void writeLabel(std::ostream& os, const UEdge& item) const {
deba@1901
   994
      if (forceLabelMap) {
deba@1429
   995
	os << graph.id(item);
deba@1429
   996
      } else {
deba@1901
   997
	labelMap->write(os, item);
deba@1429
   998
      }
deba@1429
   999
    } 
deba@1429
  1000
deba@1901
  1001
    /// \brief Write the label of the given edge.
deba@1429
  1002
    ///
deba@1901
  1003
    /// It writes the label of the given edge. If there was written 
deba@1901
  1004
    /// an "label" named map then it will write the map value belongs to the 
deba@1901
  1005
    /// edge. Otherwise if the \c forceLabel parameter was true it 
deba@1429
  1006
    /// will write its id in the graph. If the edge is forward map
deba@1429
  1007
    /// then its prefix character is \c '+' elsewhere \c '-'.
deba@1901
  1008
    void writeLabel(std::ostream& os, const Edge& item) const {
deba@1690
  1009
      if (graph.direction(item)) {
deba@1429
  1010
	os << "+ ";
deba@1429
  1011
      } else {
deba@1429
  1012
	os << "- ";
deba@1429
  1013
      }
deba@1901
  1014
      if (forceLabelMap) {
deba@1421
  1015
	os << graph.id(item);
deba@1421
  1016
      } else {
deba@1901
  1017
	labelMap->write(os, item);
deba@1421
  1018
      }
deba@1421
  1019
    } 
deba@1421
  1020
deba@1421
  1021
  private:
deba@1421
  1022
deba@1845
  1023
    typedef std::vector<std::pair<std::string, _writer_bits::
klao@1909
  1024
				  MapWriterBase<UEdge>*> > MapWriters;
deba@1421
  1025
    MapWriters writers;
deba@1421
  1026
klao@1909
  1027
    _writer_bits::MapWriterBase<UEdge>* labelMap;
deba@1901
  1028
    bool forceLabelMap;
deba@2101
  1029
    bool sortByLabel;
deba@1421
  1030
   
deba@1705
  1031
    const Graph& graph;   
deba@1901
  1032
    std::string name;
deba@1409
  1033
deba@1901
  1034
    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
deba@1409
  1035
  };
deba@1409
  1036
deba@2016
  1037
  /// \ingroup section_io
deba@1901
  1038
  /// \brief SectionWriter for writing named nodes.
deba@1409
  1039
  ///
deba@1901
  1040
  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
deba@1901
  1041
  /// \c nodes_name may be empty.
deba@1409
  1042
  ///
deba@1901
  1043
  /// Each line in the section contains the name of the node and 
deba@1901
  1044
  /// then the node label. 
deba@1409
  1045
  ///
deba@1409
  1046
  /// \relates LemonWriter
deba@1409
  1047
  template <typename _Graph>
deba@1845
  1048
  class NodeWriter : public LemonWriter::SectionWriter {
deba@1845
  1049
    typedef LemonWriter::SectionWriter Parent;
deba@1409
  1050
    typedef _Graph Graph;
deba@1429
  1051
    typedef typename Graph::Node Node;
deba@1409
  1052
  public:
deba@1409
  1053
    
deba@1409
  1054
    /// \brief Constructor.
deba@1409
  1055
    ///
deba@1409
  1056
    /// Constructor for NodeWriter. It creates the NodeWriter and
deba@1901
  1057
    /// attach it into the given LemonWriter. The given \c _LabelWriter
deba@1901
  1058
    /// will write the nodes' label what can be a nodeset writer.
deba@1901
  1059
    template <typename _LabelWriter>
deba@1901
  1060
    NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
deba@1901
  1061
	       const std::string& _name = std::string()) 
deba@1901
  1062
      : Parent(_writer), name(_name) {
deba@1901
  1063
      checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
deba@1901
  1064
      labelWriter.reset(new _writer_bits::LabelWriter<Node, _LabelWriter>
deba@1901
  1065
                        (_labelWriter));
deba@1476
  1066
    }
deba@1476
  1067
deba@1409
  1068
deba@1409
  1069
    /// \brief Destructor.
deba@1409
  1070
    ///
deba@1409
  1071
    /// Destructor for NodeWriter.
deba@1409
  1072
    virtual ~NodeWriter() {}
deba@1409
  1073
deba@1409
  1074
  private:
deba@1409
  1075
    NodeWriter(const NodeWriter&);
deba@1409
  1076
    void operator=(const NodeWriter&);
deba@1409
  1077
deba@1409
  1078
  public:
deba@1409
  1079
deba@1409
  1080
    /// \brief Add a node writer command for the NodeWriter.
deba@1409
  1081
    ///
deba@1409
  1082
    /// Add a node writer command for the NodeWriter.
deba@1429
  1083
    void writeNode(const std::string& name, const Node& item) {
deba@1409
  1084
      writers.push_back(make_pair(name, &item));
deba@1409
  1085
    }
deba@1409
  1086
deba@1409
  1087
  protected:
deba@1409
  1088
deba@1901
  1089
    /// \brief The header of the section.
deba@1409
  1090
    ///
deba@1901
  1091
    /// It gives back the header of the section.
deba@1409
  1092
    virtual std::string header() {
deba@1901
  1093
      return "@nodes " + name;
deba@1409
  1094
    }
deba@1409
  1095
deba@1409
  1096
    /// \brief  Writer function of the section.
deba@1409
  1097
    ///
deba@1409
  1098
    /// Write the content of the section.
deba@1409
  1099
    virtual void write(std::ostream& os) {
deba@1901
  1100
      if (!labelWriter->isLabelWriter()) {
deba@1901
  1101
	throw DataFormatError("Cannot find nodeset or label map");
deba@1476
  1102
      }
deba@1409
  1103
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
  1104
	os << writers[i].first << ' ';
deba@1901
  1105
	labelWriter->write(os, *(writers[i].second));
deba@1409
  1106
	os << std::endl;
deba@1409
  1107
      }
deba@1409
  1108
    }
deba@2084
  1109
deba@2084
  1110
    /// \brief Gives back true when the section should be written.
deba@2084
  1111
    ///
deba@2084
  1112
    /// Gives back true when the section should be written.
deba@2084
  1113
    virtual bool valid() { return !writers.empty(); }
deba@1409
  1114
    
deba@1409
  1115
  private:
deba@1409
  1116
deba@1901
  1117
    std::string name;
deba@1409
  1118
deba@1429
  1119
    typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
deba@1429
  1120
    NodeWriters writers;
deba@1901
  1121
    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
deba@1409
  1122
  };
deba@1409
  1123
deba@2016
  1124
  /// \ingroup section_io
deba@1901
  1125
  /// \brief SectionWriter for writing named edges.
deba@1409
  1126
  ///
deba@1901
  1127
  /// The edges section's header line is \c \@edges \c edges_name, but the
deba@1901
  1128
  /// \c edges_name may be empty.
deba@1409
  1129
  ///
deba@1901
  1130
  /// Each line in the section contains the name of the edge and 
deba@1901
  1131
  /// then the edge label. 
deba@1409
  1132
  ///
deba@1409
  1133
  /// \relates LemonWriter
deba@1409
  1134
  template <typename _Graph>
deba@1845
  1135
  class EdgeWriter : public LemonWriter::SectionWriter {
deba@1845
  1136
    typedef LemonWriter::SectionWriter Parent;
deba@1409
  1137
    typedef _Graph Graph;
deba@1429
  1138
    typedef typename Graph::Edge Edge;
deba@1409
  1139
  public:
deba@1409
  1140
    
deba@1409
  1141
    /// \brief Constructor.
deba@1409
  1142
    ///
deba@1409
  1143
    /// Constructor for EdgeWriter. It creates the EdgeWriter and
deba@1901
  1144
    /// attach it into the given LemonWriter. The given \c _LabelWriter
deba@1901
  1145
    /// will write the edges' label what can be a edgeset writer.
deba@1901
  1146
    template <typename _LabelWriter>
deba@1901
  1147
    EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
deba@1901
  1148
	       const std::string& _name = std::string()) 
deba@1901
  1149
      : Parent(_writer), name(_name) {
deba@1901
  1150
      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
deba@1901
  1151
      labelWriter.reset(new _writer_bits::LabelWriter<Edge, _LabelWriter>(_labelWriter));
deba@1476
  1152
    }
deba@1409
  1153
deba@1409
  1154
    /// \brief Destructor.
deba@1409
  1155
    ///
deba@1409
  1156
    /// Destructor for EdgeWriter.
deba@1409
  1157
    virtual ~EdgeWriter() {}
deba@1409
  1158
  private:
deba@1409
  1159
    EdgeWriter(const EdgeWriter&);
deba@1409
  1160
    void operator=(const EdgeWriter&);
deba@1409
  1161
deba@1409
  1162
  public:
deba@1409
  1163
deba@1421
  1164
    /// \brief Add an edge writer command for the EdgeWriter.
deba@1409
  1165
    ///
deba@1421
  1166
    /// Add an edge writer command for the EdgeWriter.
deba@1429
  1167
    void writeEdge(const std::string& name, const Edge& item) {
deba@1409
  1168
      writers.push_back(make_pair(name, &item));
deba@1409
  1169
    }
deba@1409
  1170
deba@1409
  1171
  protected:
deba@1409
  1172
deba@1901
  1173
    /// \brief The header of the section.
deba@1409
  1174
    ///
deba@1901
  1175
    /// It gives back the header of the section.
deba@1421
  1176
    virtual std::string header() {
deba@1901
  1177
      return "@edges " + name;
deba@1421
  1178
    }
deba@1421
  1179
deba@1421
  1180
    /// \brief  Writer function of the section.
deba@1421
  1181
    ///
deba@1421
  1182
    /// Write the content of the section.
deba@1421
  1183
    virtual void write(std::ostream& os) {
deba@1901
  1184
      if (!labelWriter->isLabelWriter()) {
deba@1901
  1185
	throw DataFormatError("Cannot find edgeset or label map");
deba@1476
  1186
      }
deba@1421
  1187
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1421
  1188
	os << writers[i].first << ' ';
deba@1901
  1189
	labelWriter->write(os, *(writers[i].second));
deba@1421
  1190
	os << std::endl;
deba@1421
  1191
      }
deba@1421
  1192
    }
deba@2084
  1193
deba@2084
  1194
    /// \brief Gives back true when the section should be written.
deba@2084
  1195
    ///
deba@2084
  1196
    /// Gives back true when the section should be written.
deba@2084
  1197
    virtual bool valid() { return !writers.empty(); }
deba@1421
  1198
    
deba@1421
  1199
  private:
deba@1421
  1200
deba@1901
  1201
    std::string name;
deba@1421
  1202
deba@1429
  1203
    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
deba@1429
  1204
    EdgeWriters writers;
deba@1421
  1205
deba@1901
  1206
    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
deba@1421
  1207
  };
deba@1421
  1208
deba@2016
  1209
  /// \ingroup section_io
deba@1901
  1210
  /// \brief SectionWriter for writing named undirected edges.
deba@1421
  1211
  ///
klao@1909
  1212
  /// The undirected edges section's header line is \c \@uedges 
klao@1909
  1213
  /// \c uedges_name, but the \c uedges_name may be empty.
deba@1421
  1214
  ///
deba@1901
  1215
  /// Each line in the section contains the name of the undirected edge and 
deba@1901
  1216
  /// then the undirected edge label. 
deba@1421
  1217
  ///
deba@1421
  1218
  /// \relates LemonWriter
deba@1421
  1219
  template <typename _Graph>
klao@1909
  1220
  class UEdgeWriter : public LemonWriter::SectionWriter {
deba@1845
  1221
    typedef LemonWriter::SectionWriter Parent;
deba@1421
  1222
    typedef _Graph Graph;
deba@1429
  1223
    typedef typename Graph::Node Node;
deba@1429
  1224
    typedef typename Graph::Edge Edge;
klao@1909
  1225
    typedef typename Graph::UEdge UEdge;
deba@1421
  1226
  public:
deba@1421
  1227
    
deba@1421
  1228
    /// \brief Constructor.
deba@1421
  1229
    ///
klao@1909
  1230
    /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
deba@1901
  1231
    /// attach it into the given LemonWriter. The given \c _LabelWriter
deba@1901
  1232
    /// will write the undirected edges' label what can be an undirected 
deba@1421
  1233
    /// edgeset writer.
deba@1901
  1234
    template <typename _LabelWriter>
klao@1909
  1235
    UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, 
deba@1901
  1236
	       const std::string& _name = std::string()) 
deba@1901
  1237
      : Parent(_writer), name(_name) {
deba@1901
  1238
      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
klao@1909
  1239
      checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
klao@1909
  1240
      uEdgeLabelWriter.reset(new _writer_bits::
klao@1909
  1241
			      LabelWriter<UEdge, _LabelWriter>(_labelWriter));
deba@1901
  1242
      edgeLabelWriter.reset(new _writer_bits::
deba@1901
  1243
			 LabelWriter<Edge, _LabelWriter>(_labelWriter));
deba@1476
  1244
    }
deba@1421
  1245
deba@1421
  1246
    /// \brief Destructor.
deba@1421
  1247
    ///
klao@1909
  1248
    /// Destructor for UEdgeWriter.
klao@1909
  1249
    virtual ~UEdgeWriter() {}
deba@1421
  1250
  private:
klao@1909
  1251
    UEdgeWriter(const UEdgeWriter&);
klao@1909
  1252
    void operator=(const UEdgeWriter&);
deba@1421
  1253
deba@1421
  1254
  public:
deba@1421
  1255
klao@1909
  1256
    /// \brief Add an edge writer command for the UEdgeWriter.
deba@1429
  1257
    ///
klao@1909
  1258
    /// Add an edge writer command for the UEdgeWriter.
deba@1429
  1259
    void writeEdge(const std::string& name, const Edge& item) {
deba@1429
  1260
      edgeWriters.push_back(make_pair(name, &item));
deba@1429
  1261
    }
deba@1429
  1262
klao@1909
  1263
    /// \brief Add an undirected edge writer command for the UEdgeWriter.
deba@1421
  1264
    ///
klao@1909
  1265
    /// Add an undirected edge writer command for the UEdgeWriter.
klao@1909
  1266
    void writeUEdge(const std::string& name, const UEdge& item) {
klao@1909
  1267
      uEdgeWriters.push_back(make_pair(name, &item));
deba@1421
  1268
    }
deba@1421
  1269
deba@1421
  1270
  protected:
deba@1421
  1271
deba@1901
  1272
    /// \brief The header of the section.
deba@1421
  1273
    ///
deba@1901
  1274
    /// It gives back the header of the section.
deba@1409
  1275
    virtual std::string header() {
klao@1909
  1276
      return "@uedges " + name;
deba@1409
  1277
    }
deba@1409
  1278
deba@1409
  1279
    /// \brief  Writer function of the section.
deba@1409
  1280
    ///
deba@1409
  1281
    /// Write the content of the section.
deba@1409
  1282
    virtual void write(std::ostream& os) {
deba@1901
  1283
      if (!edgeLabelWriter->isLabelWriter()) {
deba@1901
  1284
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  1285
      }
klao@1909
  1286
      if (!uEdgeLabelWriter->isLabelWriter()) {
deba@1901
  1287
	throw DataFormatError("Cannot find undirected edgeset or label map");
deba@1476
  1288
      }
klao@1909
  1289
      for (int i = 0; i < (int)uEdgeWriters.size(); ++i) {
klao@1909
  1290
	os << uEdgeWriters[i].first << ' ';
klao@1909
  1291
	uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
deba@1429
  1292
	os << std::endl;
deba@1429
  1293
      }
deba@1429
  1294
      for (int i = 0; i < (int)edgeWriters.size(); ++i) {
deba@1429
  1295
	os << edgeWriters[i].first << ' ';
deba@1901
  1296
	edgeLabelWriter->write(os, *(edgeWriters[i].second));
deba@1409
  1297
	os << std::endl;
deba@1409
  1298
      }
deba@1409
  1299
    }
deba@2084
  1300
deba@2084
  1301
    /// \brief Gives back true when the section should be written.
deba@2084
  1302
    ///
deba@2084
  1303
    /// Gives back true when the section should be written.
deba@2084
  1304
    virtual bool valid() { 
deba@2084
  1305
      return !uEdgeWriters.empty() || !edgeWriters.empty(); 
deba@2084
  1306
    }
deba@1409
  1307
    
deba@1409
  1308
  private:
deba@1409
  1309
deba@1901
  1310
    std::string name;
deba@1409
  1311
deba@1429
  1312
    typedef std::vector<std::pair<std::string, 
klao@1909
  1313
				  const UEdge*> > UEdgeWriters;
klao@1909
  1314
    UEdgeWriters uEdgeWriters;
klao@1909
  1315
    std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
deba@1409
  1316
deba@1429
  1317
    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
deba@1429
  1318
    EdgeWriters edgeWriters;
deba@1901
  1319
    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
deba@1429
  1320
deba@1409
  1321
  };
deba@1409
  1322
deba@2016
  1323
  /// \ingroup section_io
deba@1409
  1324
  /// \brief SectionWriter for attributes.
deba@1409
  1325
  ///
deba@1409
  1326
  /// The lemon format can store multiple attribute set. Each set has
deba@1901
  1327
  /// the header line \c \@attributes \c attributes_name, but the 
deba@1901
  1328
  /// attributeset_name may be empty.
deba@1409
  1329
  ///
deba@1409
  1330
  /// The attributeset section contains several lines. Each of them starts
deba@1409
  1331
  /// with the name of attribute and then the value.
deba@1409
  1332
  ///
deba@1409
  1333
  /// \relates LemonWriter
deba@1409
  1334
  template <typename _Traits = DefaultWriterTraits>
deba@1845
  1335
  class AttributeWriter : public LemonWriter::SectionWriter {
deba@1845
  1336
    typedef LemonWriter::SectionWriter Parent;
deba@1409
  1337
    typedef _Traits Traits; 
deba@1409
  1338
  public:
deba@1409
  1339
    /// \brief Constructor.
deba@1409
  1340
    ///
deba@1409
  1341
    /// Constructor for AttributeWriter. It creates the AttributeWriter and
deba@1409
  1342
    /// attach it into the given LemonWriter.
deba@1409
  1343
    AttributeWriter(LemonWriter& _writer, 
deba@1901
  1344
		    const std::string& _name = std::string()) 
deba@1901
  1345
      : Parent(_writer), name(_name) {}
deba@1409
  1346
deba@1409
  1347
    /// \brief Destructor.
deba@1409
  1348
    ///
deba@1409
  1349
    /// Destructor for AttributeWriter.
deba@1409
  1350
    virtual ~AttributeWriter() {
deba@1409
  1351
      typename Writers::iterator it;
deba@1409
  1352
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
  1353
	delete it->second;
deba@1409
  1354
      }
deba@1409
  1355
    }
deba@1409
  1356
deba@1409
  1357
  private:
deba@1409
  1358
    AttributeWriter(const AttributeWriter&);
deba@1409
  1359
    void operator=(AttributeWriter&);
deba@1409
  1360
deba@1409
  1361
  public:
deba@1409
  1362
    /// \brief Add an attribute writer command for the writer.
deba@1409
  1363
    ///
deba@1409
  1364
    /// Add an attribute writer command for the writer.
deba@1409
  1365
    template <typename Value>
deba@1901
  1366
    AttributeWriter& writeAttribute(const std::string& name, 
deba@1409
  1367
				    const Value& value) {
deba@1409
  1368
      return 
deba@1901
  1369
	writeAttribute<typename Traits::template Writer<Value> >(name, value);
deba@1409
  1370
    }
deba@1409
  1371
deba@1409
  1372
    /// \brief Add an attribute writer command for the writer.
deba@1409
  1373
    ///
deba@1409
  1374
    /// Add an attribute writer command for the writer.
deba@1409
  1375
    template <typename Writer, typename Value>
deba@1409
  1376
    AttributeWriter& writeAttribute(const std::string& name, 
deba@1409
  1377
				    const Value& value,
deba@1409
  1378
				    const Writer& writer = Writer()) {
deba@1492
  1379
      checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
deba@1845
  1380
      writers.push_back(make_pair(name, new _writer_bits::
deba@1845
  1381
				  ValueWriter<Value, Writer>(value, writer)));
deba@1409
  1382
      return *this;
deba@1409
  1383
    }
deba@1409
  1384
deba@1409
  1385
  protected:
deba@1409
  1386
deba@1409
  1387
    /// \brief The header of section.
deba@1409
  1388
    ///
deba@1409
  1389
    /// It gives back the header of the section.
deba@1409
  1390
    std::string header() {
deba@1901
  1391
      return "@attributes " + name;
deba@1409
  1392
    }
deba@1409
  1393
deba@1409
  1394
    /// \brief  Writer function of the section.
deba@1409
  1395
    ///
deba@1409
  1396
    /// Write the content of the section.
deba@1409
  1397
    void write(std::ostream& os) {
deba@1409
  1398
      typename Writers::iterator it;
deba@1409
  1399
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
  1400
	os << it->first << ' ';
deba@1409
  1401
	it->second->write(os);
deba@1409
  1402
	os << std::endl;
deba@1409
  1403
      }
deba@1409
  1404
    }    
deba@1409
  1405
deba@2084
  1406
    /// \brief Gives back true when the section should be written.
deba@2084
  1407
    ///
deba@2084
  1408
    /// Gives back true when the section should be written.
deba@2084
  1409
    virtual bool valid() { return !writers.empty(); }
deba@2084
  1410
deba@1409
  1411
  private:
deba@1901
  1412
    std::string name;
deba@1409
  1413
deba@1845
  1414
    typedef std::vector<std::pair<std::string, 
deba@1845
  1415
				  _writer_bits::ValueWriterBase*> > Writers;
deba@1409
  1416
    Writers writers;  
deba@1409
  1417
  };
deba@1409
  1418
deba@1409
  1419
deba@1409
  1420
}
deba@1409
  1421
#endif