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