src/lemon/lemon_writer.h
author deba
Wed, 11 May 2005 13:49:17 +0000
changeset 1411 5d161e08bda8
parent 1409 d2d1f8fa187b
child 1421 7a21e1414c38
permissions -rw-r--r--
Bug fix.
deba@1409
     1
/* -*- C++ -*-
deba@1409
     2
 * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
deba@1409
     3
 *
deba@1409
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1409
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1409
     6
 *
deba@1409
     7
 * Permission to use, modify and distribute this software is granted
deba@1409
     8
 * provided that this copyright notice appears in all copies. For
deba@1409
     9
 * precise terms see the accompanying LICENSE file.
deba@1409
    10
 *
deba@1409
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1409
    12
 * express or implied, and with no claim as to its suitability for any
deba@1409
    13
 * purpose.
deba@1409
    14
 *
deba@1409
    15
 */
deba@1409
    16
deba@1409
    17
///\ingroup io_group
deba@1409
    18
///\file
deba@1409
    19
///\brief Lemon Format writer.
deba@1409
    20
deba@1409
    21
#ifndef LEMON_LEMON_WRITER_H
deba@1409
    22
#define LEMON_LEMON_WRITER_H
deba@1409
    23
deba@1409
    24
#include <iostream>
deba@1409
    25
#include <fstream>
deba@1409
    26
#include <string>
deba@1409
    27
#include <vector>
deba@1409
    28
#include <algorithm>
deba@1409
    29
#include <map>
deba@1409
    30
#include <memory>
deba@1409
    31
deba@1409
    32
#include <lemon/error.h>
deba@1409
    33
#include <lemon/invalid.h>
deba@1409
    34
#include <lemon/bits/item_writer.h>
deba@1409
    35
deba@1409
    36
deba@1409
    37
namespace lemon {
deba@1409
    38
deba@1409
    39
  /// \ingroup io_group
deba@1409
    40
  /// \brief Lemon Format writer class.
deba@1409
    41
  /// 
deba@1409
    42
  /// The Lemon Format contains several sections. We do not want to
deba@1409
    43
  /// determine what sections are in a lemon file we give only a framework
deba@1409
    44
  /// to write a section oriented format.
deba@1409
    45
  ///
deba@1409
    46
  /// In the Lemon Format each section starts with a line contains a \c \@
deba@1409
    47
  /// character on the first not white space position. This line is the
deba@1409
    48
  /// header line of the section. Each next lines belong to this section
deba@1409
    49
  /// while it does not starts with \c \@ character. This line can start a 
deba@1409
    50
  /// new section or if it can close the file with the \c \@end line.
deba@1409
    51
  /// The file format ignore the empty lines and it may contain comments
deba@1409
    52
  /// started with a \c # character to the end of the line. 
deba@1409
    53
  ///
deba@1409
    54
  /// The framework provides an abstract LemonWriter::SectionWriter class
deba@1409
    55
  /// what defines the interface of a SectionWriter. The SectionWriter
deba@1409
    56
  /// has the \c header() member function what gives back the header of the
deba@1409
    57
  /// section. After that it will be called the \c write() member which
deba@1409
    58
  /// should write the content of the section.
deba@1409
    59
  ///
deba@1409
    60
  /// \relates GraphWriter
deba@1409
    61
  /// \relates NodeSetWriter
deba@1409
    62
  /// \relates EdgeSetWriter
deba@1409
    63
  /// \relates NodesWriter
deba@1409
    64
  /// \relates EdgesWriter
deba@1409
    65
  /// \relates AttributeWriter
deba@1409
    66
  class LemonWriter {
deba@1409
    67
  public:
deba@1409
    68
deba@1409
    69
    /// \brief Abstract base class for writing a section.
deba@1409
    70
    ///
deba@1409
    71
    /// This class has an \c header() member function what gives back
deba@1409
    72
    /// the header line of the section. The \c write() member should
deba@1409
    73
    /// write the content of the section to the stream.
deba@1409
    74
    class SectionWriter {
deba@1409
    75
      friend class LemonWriter;
deba@1409
    76
    protected:
deba@1409
    77
      /// \brief Constructor for SectionWriter.
deba@1409
    78
      ///
deba@1409
    79
      /// Constructor for SectionWriter. It attach this writer to
deba@1409
    80
      /// the given LemonWriter.
deba@1409
    81
      SectionWriter(LemonWriter& writer) {
deba@1409
    82
	writer.attach(*this);
deba@1409
    83
      }
deba@1409
    84
deba@1409
    85
      /// \brief The header of section.
deba@1409
    86
      ///
deba@1409
    87
      /// It gives back the header of the section.
deba@1409
    88
      virtual std::string header() = 0;
deba@1409
    89
deba@1409
    90
      /// \brief  Writer function of the section.
deba@1409
    91
      ///
deba@1409
    92
      /// Write the content of the section.
deba@1409
    93
      virtual void write(std::ostream& os) = 0;
deba@1409
    94
    };
deba@1409
    95
deba@1409
    96
    /// \brief Constructor for LemonWriter.
deba@1409
    97
    ///
deba@1409
    98
    /// Constructor for LemonWriter which writes to the given stream.
deba@1409
    99
    LemonWriter(std::ostream& _os) 
deba@1409
   100
      : os(&_os), own_os(false) {}
deba@1409
   101
deba@1409
   102
    /// \brief Constructor for LemonWriter.
deba@1409
   103
    ///
deba@1409
   104
    /// Constructor for LemonWriter which writes to the given file.
deba@1409
   105
    LemonWriter(const std::string& filename) 
deba@1409
   106
      : os(0), own_os(true) {
deba@1409
   107
      os = new std::ofstream(filename.c_str());
deba@1409
   108
    }
deba@1409
   109
deba@1409
   110
    /// \brief Desctructor for LemonWriter.
deba@1409
   111
    ///
deba@1409
   112
    /// Desctructor for LemonWriter.
deba@1409
   113
    ~LemonWriter() {
deba@1409
   114
      if (own_os) {
deba@1409
   115
	delete os;
deba@1409
   116
      }
deba@1409
   117
    }
deba@1409
   118
deba@1409
   119
  private:
deba@1409
   120
    LemonWriter(const LemonWriter&);
deba@1409
   121
    void operator=(const LemonWriter&);
deba@1409
   122
deba@1409
   123
    void attach(SectionWriter& writer) {
deba@1409
   124
      writers.push_back(&writer);
deba@1409
   125
    }
deba@1409
   126
deba@1409
   127
  public:
deba@1409
   128
deba@1409
   129
    /// \brief Executes the LemonWriter.
deba@1409
   130
    /// 
deba@1409
   131
    /// It executes the LemonWriter.
deba@1409
   132
    void run() {
deba@1409
   133
      SectionWriters::iterator it;
deba@1409
   134
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   135
	*os << (*it)->header() << std::endl;
deba@1409
   136
	(*it)->write(*os);
deba@1409
   137
      }
deba@1409
   138
      *os << "@end" << std::endl;
deba@1409
   139
    }
deba@1409
   140
deba@1409
   141
deba@1409
   142
  private:
deba@1409
   143
deba@1409
   144
    std::ostream* os;
deba@1409
   145
    bool own_os;
deba@1409
   146
deba@1409
   147
    typedef std::vector<SectionWriter*> SectionWriters;
deba@1409
   148
    SectionWriters writers;
deba@1409
   149
deba@1409
   150
  };
deba@1409
   151
deba@1409
   152
  /// \brief Helper class for implementing the common SectionWriters.
deba@1409
   153
  ///
deba@1409
   154
  /// Helper class for implementing the common SectionWriters.
deba@1409
   155
  class CommonSectionWriterBase : public LemonWriter::SectionWriter {
deba@1409
   156
    typedef LemonWriter::SectionWriter Parent;
deba@1409
   157
  protected:
deba@1409
   158
    
deba@1409
   159
    /// \brief Constructor for CommonSectionWriterBase.
deba@1409
   160
    ///
deba@1409
   161
    /// Constructor for CommonSectionWriterBase. It attach this writer to
deba@1409
   162
    /// the given LemonWriter.
deba@1409
   163
    CommonSectionWriterBase(LemonWriter& _writer) 
deba@1409
   164
      : Parent(_writer) {}
deba@1409
   165
deba@1409
   166
    // Writers
deba@1409
   167
deba@1409
   168
    template <typename _Item>    
deba@1409
   169
    class WriterBase {
deba@1409
   170
    public:
deba@1409
   171
      typedef _Item Item;
deba@1409
   172
deba@1409
   173
      virtual ~WriterBase() {}
deba@1409
   174
deba@1409
   175
      virtual void write(std::ostream& os, const Item& item) = 0;
deba@1409
   176
    };
deba@1409
   177
deba@1409
   178
deba@1409
   179
    template <typename _Item, typename _Map, typename _Writer>
deba@1409
   180
    class MapWriter : public WriterBase<_Item> {
deba@1409
   181
    public:
deba@1409
   182
      typedef _Map Map;
deba@1409
   183
      typedef _Writer Writer;
deba@1409
   184
      typedef typename Writer::Value Value;
deba@1409
   185
      typedef _Item Item;
deba@1409
   186
      
deba@1409
   187
      const Map& map;
deba@1409
   188
      Writer writer;
deba@1409
   189
deba@1409
   190
      MapWriter(const Map& _map, const Writer& _writer) 
deba@1409
   191
	: map(_map), writer(_writer) {}
deba@1409
   192
deba@1409
   193
      virtual ~MapWriter() {}
deba@1409
   194
deba@1409
   195
      virtual void write(std::ostream& os, const Item& item) {
deba@1409
   196
	Value value = map[item];
deba@1409
   197
	writer.write(os, value);
deba@1409
   198
      }
deba@1409
   199
deba@1409
   200
    };
deba@1409
   201
deba@1409
   202
deba@1409
   203
    class ValueWriterBase {
deba@1409
   204
    public:
deba@1409
   205
      virtual void write(std::ostream&) = 0;
deba@1409
   206
    };
deba@1409
   207
deba@1409
   208
    template <typename _Value, typename _Writer>
deba@1409
   209
    class ValueWriter : public ValueWriterBase {
deba@1409
   210
    public:
deba@1409
   211
      typedef _Value Value;
deba@1409
   212
      typedef _Writer Writer;
deba@1409
   213
deba@1409
   214
      ValueWriter(const Value& _value, const Writer& _writer)
deba@1409
   215
 	: value(_value), writer(_writer) {}
deba@1409
   216
deba@1409
   217
      virtual void write(std::ostream& os) {
deba@1411
   218
	writer.write(os, value);
deba@1409
   219
      }
deba@1409
   220
    private:
deba@1409
   221
      const Value& value;
deba@1409
   222
      Writer writer;
deba@1409
   223
    };
deba@1409
   224
    
deba@1409
   225
deba@1409
   226
    template <typename _Item>
deba@1409
   227
    class IdWriterBase {
deba@1409
   228
    public:
deba@1409
   229
      typedef _Item Item;
deba@1409
   230
      virtual void write(std::ostream&, const Item&) const = 0;
deba@1409
   231
    };
deba@1409
   232
deba@1409
   233
    template <typename _Item, typename _BoxedIdWriter>
deba@1409
   234
    class IdWriter : public IdWriterBase<_Item> {
deba@1409
   235
    public:
deba@1409
   236
      typedef _Item Item;
deba@1409
   237
      typedef _BoxedIdWriter BoxedIdWriter;
deba@1409
   238
deba@1409
   239
      const BoxedIdWriter& idWriter;
deba@1409
   240
deba@1409
   241
      IdWriter(const BoxedIdWriter& _idWriter) 
deba@1409
   242
	: idWriter(_idWriter) {}
deba@1409
   243
deba@1409
   244
      virtual void write(std::ostream& os, const Item& item) const {
deba@1409
   245
	return idWriter.writeId(os, item);
deba@1409
   246
      }
deba@1409
   247
    };
deba@1409
   248
  };
deba@1409
   249
deba@1409
   250
  /// \ingroup io_group
deba@1409
   251
  /// \brief SectionWriter for writing a graph's nodeset.
deba@1409
   252
  ///
deba@1409
   253
  /// The lemon format can store multiple graph nodesets with several maps.
deba@1409
   254
  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
deba@1409
   255
  /// \c nodeset_id may be empty.
deba@1409
   256
  ///
deba@1409
   257
  /// The first line of the section contains the names of the maps separated
deba@1409
   258
  /// with white spaces. Each next lines describes a node in the nodeset, and
deba@1409
   259
  /// contains the mapped values for each map.
deba@1409
   260
  ///
deba@1409
   261
  /// If the nodeset contains an \c "id" named map then it will be regarded
deba@1409
   262
  /// as id map. This map should contain only unique values and when the 
deba@1409
   263
  /// \c writeId() member will be called with a node it will write it's id.
deba@1409
   264
  /// Otherwise if the \c _forceIdMap constructor parameter is true then
deba@1409
   265
  /// the id map will be the id in the graph.
deba@1409
   266
  ///
deba@1409
   267
  /// \relates LemonWriter
deba@1409
   268
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1409
   269
  class NodeSetWriter : public CommonSectionWriterBase {
deba@1409
   270
    typedef CommonSectionWriterBase Parent;
deba@1409
   271
  public:
deba@1409
   272
deba@1409
   273
    typedef _Graph Graph;
deba@1409
   274
    typedef _Traits Traits;
deba@1409
   275
    typedef typename Graph::Node Item;
deba@1409
   276
deba@1409
   277
    /// \brief Constructor.
deba@1409
   278
    ///
deba@1409
   279
    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
deba@1409
   280
    /// attach it into the given LemonWriter. If the \c _forceIdMap
deba@1409
   281
    /// parameter is true then the writer will write own id map when
deba@1409
   282
    /// the user does not give "id" named map.
deba@1409
   283
    NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1409
   284
		  const std::string& _id = std::string(), 
deba@1409
   285
		  bool _forceIdMap = true) 
deba@1409
   286
      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), 
deba@1409
   287
	graph(_graph), id(_id) {}
deba@1409
   288
deba@1409
   289
    /// \brief Destructor.
deba@1409
   290
    ///
deba@1409
   291
    /// Destructor for NodeSetWriter.
deba@1409
   292
    virtual ~NodeSetWriter() {
deba@1409
   293
      typename MapWriters::iterator it;
deba@1409
   294
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   295
	delete it->second;
deba@1409
   296
      }
deba@1409
   297
    }
deba@1409
   298
deba@1409
   299
  private:
deba@1409
   300
    NodeSetWriter(const NodeSetWriter&);
deba@1409
   301
    void operator=(const NodeSetWriter&);
deba@1409
   302
  
deba@1409
   303
  public:
deba@1409
   304
deba@1409
   305
    /// \brief Add a new node map writer command for the writer.
deba@1409
   306
    ///
deba@1409
   307
    /// Add a new node map writer command for the writer.
deba@1409
   308
    template <typename Map>
deba@1409
   309
    NodeSetWriter& writeMap(std::string name, const Map& map) {
deba@1409
   310
      return writeMap<typename Traits::
deba@1409
   311
	template Writer<typename Map::Value>, Map>(name, map);
deba@1409
   312
    }
deba@1409
   313
deba@1409
   314
    /// \brief Add a new node map writer command for the writer.
deba@1409
   315
    ///
deba@1409
   316
    /// Add a new node map writer command for the writer.
deba@1409
   317
    template <typename Writer, typename Map>
deba@1409
   318
    NodeSetWriter& writeMap(std::string name, const Map& map, 
deba@1409
   319
			     const Writer& writer = Writer()) {
deba@1409
   320
      writers.push_back(
deba@1409
   321
	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
deba@1409
   322
      return *this;
deba@1409
   323
    }
deba@1409
   324
deba@1409
   325
  protected:
deba@1409
   326
deba@1409
   327
    /// \brief The header of the section.
deba@1409
   328
    ///
deba@1409
   329
    /// It gives back the header of the section.
deba@1409
   330
    virtual std::string header() {
deba@1409
   331
      return "@nodeset " + id;
deba@1409
   332
    }
deba@1409
   333
deba@1409
   334
    /// \brief  Writer function of the section.
deba@1409
   335
    ///
deba@1409
   336
    /// Write the content of the section.
deba@1409
   337
    virtual void write(std::ostream& os) {
deba@1409
   338
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   339
	if (writers[i].first == "id") {
deba@1409
   340
	  idMap = writers[i].second;
deba@1409
   341
	  forceIdMap = false;
deba@1409
   342
	  break;
deba@1409
   343
	}
deba@1409
   344
      }
deba@1409
   345
      if (forceIdMap) {
deba@1409
   346
	os << "id\t";
deba@1409
   347
      }
deba@1409
   348
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   349
	os << writers[i].first << '\t';
deba@1409
   350
      }
deba@1409
   351
      os << std::endl;
deba@1409
   352
      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
deba@1409
   353
	if (forceIdMap) {
deba@1409
   354
	  os << graph.id(it) << '\t';
deba@1409
   355
	}
deba@1409
   356
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   357
	  writers[i].second->write(os, it);
deba@1409
   358
	  os << '\t';
deba@1409
   359
	}
deba@1409
   360
	os << std::endl;
deba@1409
   361
      }
deba@1409
   362
    }
deba@1409
   363
deba@1409
   364
  public:
deba@1409
   365
deba@1409
   366
    /// \brief Returns true if the nodeset can write the ids of the nodes.
deba@1409
   367
    ///
deba@1409
   368
    /// Returns true if the nodeset can write the ids of the nodes.
deba@1409
   369
    /// It is possible only if an "id" named map was written or the 
deba@1409
   370
    /// \c _forceIdMap constructor parameter was true.
deba@1409
   371
    bool isIdWriter() const {
deba@1409
   372
      return idMap != 0 || forceIdMap;
deba@1409
   373
    }
deba@1409
   374
deba@1409
   375
    /// \brief Write the id of the given node.
deba@1409
   376
    ///
deba@1409
   377
    /// It writes the id of the given node. If there was written an "id"
deba@1409
   378
    /// named map then it will write the map value belongs to the node.
deba@1409
   379
    /// Otherwise if the \c forceId parameter was true it will write
deba@1409
   380
    /// its id in the graph. 
deba@1409
   381
    void writeId(std::ostream& os, const Item& item) const {
deba@1409
   382
      if (forceIdMap) {
deba@1409
   383
	os << graph.id(item);
deba@1409
   384
      } else {
deba@1409
   385
	idMap->write(os, item);
deba@1409
   386
      }
deba@1409
   387
    }
deba@1409
   388
deba@1409
   389
  private:
deba@1409
   390
deba@1409
   391
    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
deba@1409
   392
    MapWriters writers;
deba@1409
   393
deba@1409
   394
    WriterBase<Item>* idMap;
deba@1409
   395
    bool forceIdMap;
deba@1409
   396
   
deba@1409
   397
    const Graph& graph;   
deba@1409
   398
    std::string id;
deba@1409
   399
deba@1409
   400
  };
deba@1409
   401
deba@1409
   402
  /// \ingroup io_group
deba@1409
   403
  /// \brief SectionWriter for writing a graph's edgeset.
deba@1409
   404
  ///
deba@1409
   405
  /// The lemon format can store multiple graph edgesets with several maps.
deba@1409
   406
  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
deba@1409
   407
  /// \c edgeset_id may be empty.
deba@1409
   408
  ///
deba@1409
   409
  /// The first line of the section contains the names of the maps separated
deba@1409
   410
  /// with white spaces. Each next lines describes a edge in the edgeset. The
deba@1409
   411
  /// line contains the source and the target nodes' id and the mapped 
deba@1409
   412
  /// values for each map.
deba@1409
   413
  ///
deba@1409
   414
  /// If the edgeset contains an \c "id" named map then it will be regarded
deba@1409
   415
  /// as id map. This map should contain only unique values and when the 
deba@1409
   416
  /// \c writeId() member will be called with a edge it will write it's id.
deba@1409
   417
  /// Otherwise if the \c _forceIdMap constructor parameter is true then
deba@1409
   418
  /// the id map will be the id in the graph.
deba@1409
   419
  ///
deba@1409
   420
  /// The edgeset writer needs a node id writer to identify which nodes
deba@1409
   421
  /// have to be connected. If a NodeSetWriter can write the nodes' id,
deba@1409
   422
  /// it will be able to use with this class.
deba@1409
   423
  ///
deba@1409
   424
  /// \relates LemonWriter
deba@1409
   425
  template <typename _Graph, typename _Traits = DefaultWriterTraits>
deba@1409
   426
  class EdgeSetWriter : public CommonSectionWriterBase {
deba@1409
   427
    typedef CommonSectionWriterBase Parent;
deba@1409
   428
  public:
deba@1409
   429
deba@1409
   430
    typedef _Graph Graph;
deba@1409
   431
    typedef _Traits Traits;
deba@1409
   432
    typedef typename Graph::Edge Item;
deba@1409
   433
deba@1409
   434
    /// \brief Constructor.
deba@1409
   435
    ///
deba@1409
   436
    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
deba@1409
   437
    /// attach it into the given LemonWriter. It will write node ids by
deba@1409
   438
    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
deba@1409
   439
    /// then the writer will write own id map when the user does not give 
deba@1409
   440
    /// "id" named map.
deba@1409
   441
    template <typename NodeIdWriter>
deba@1409
   442
    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
deba@1409
   443
		  const NodeIdWriter& _nodeIdWriter, 
deba@1409
   444
		  const std::string& _id = std::string(),
deba@1409
   445
		  bool _forceIdMap = true)
deba@1409
   446
      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
deba@1409
   447
	graph(_graph), id(_id),
deba@1409
   448
	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
deba@1409
   449
		     (_nodeIdWriter)) {} 
deba@1409
   450
deba@1409
   451
    /// \brief Destructor.
deba@1409
   452
    ///
deba@1409
   453
    /// Destructor for EdgeSetWriter.
deba@1409
   454
    virtual ~EdgeSetWriter() {
deba@1409
   455
      typename MapWriters::iterator it;
deba@1409
   456
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   457
	delete it->second;
deba@1409
   458
      }
deba@1409
   459
    }
deba@1409
   460
deba@1409
   461
  private:
deba@1409
   462
    EdgeSetWriter(const EdgeSetWriter&);
deba@1409
   463
    void operator=(const EdgeSetWriter&);
deba@1409
   464
deba@1409
   465
  public:
deba@1409
   466
deba@1409
   467
    /// \brief Add a new node map writer command for the writer.
deba@1409
   468
    ///
deba@1409
   469
    /// Add a new node map writer command for the writer.
deba@1409
   470
    template <typename Map>
deba@1409
   471
    EdgeSetWriter& writeMap(std::string name, const Map& map) {
deba@1409
   472
      return writeMap<typename Traits::
deba@1409
   473
	template Writer<typename Map::Value>, Map>(name, map);
deba@1409
   474
    }
deba@1409
   475
deba@1409
   476
    /// \brief Add a new node map writer command for the writer.
deba@1409
   477
    ///
deba@1409
   478
    /// Add a new node map writer command for the writer.
deba@1409
   479
    template <typename Writer, typename Map>
deba@1409
   480
    EdgeSetWriter& writeMap(std::string name, const Map& map, 
deba@1409
   481
			     const Writer& writer = Writer()) {
deba@1409
   482
      writers.push_back(
deba@1409
   483
	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
deba@1409
   484
      return *this;
deba@1409
   485
    }
deba@1409
   486
deba@1409
   487
  protected:
deba@1409
   488
deba@1409
   489
    /// \brief The header of the section.
deba@1409
   490
    ///
deba@1409
   491
    /// It gives back the header of the section.
deba@1409
   492
    virtual std::string header() {
deba@1409
   493
      return "@edgeset " + id;
deba@1409
   494
    }
deba@1409
   495
deba@1409
   496
    /// \brief  Writer function of the section.
deba@1409
   497
    ///
deba@1409
   498
    /// Write the content of the section.
deba@1409
   499
    virtual void write(std::ostream& os) {
deba@1409
   500
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   501
	if (writers[i].first == "id") {
deba@1409
   502
	  idMap = writers[i].second;
deba@1409
   503
	  forceIdMap = false;
deba@1409
   504
	  break;
deba@1409
   505
	}
deba@1409
   506
      }
deba@1409
   507
      os << "\t\t";
deba@1409
   508
      if (forceIdMap) {
deba@1409
   509
	os << "id\t";
deba@1409
   510
      }
deba@1409
   511
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   512
	os << writers[i].first << '\t';
deba@1409
   513
      }
deba@1409
   514
      os << std::endl;
deba@1409
   515
      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
deba@1409
   516
	nodeIdWriter->write(os, graph.source(it));
deba@1409
   517
	os << '\t';
deba@1409
   518
	nodeIdWriter->write(os, graph.target(it));
deba@1409
   519
	os << '\t';
deba@1409
   520
	if (forceIdMap) {
deba@1409
   521
	  os << graph.id(it) << '\t';
deba@1409
   522
	}
deba@1409
   523
	for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   524
	  writers[i].second->write(os, it);
deba@1409
   525
	  os << '\t';
deba@1409
   526
	}
deba@1409
   527
	os << std::endl;
deba@1409
   528
      }
deba@1409
   529
    }
deba@1409
   530
deba@1409
   531
  public:
deba@1409
   532
deba@1409
   533
    /// \brief Returns true if the edgeset can write the ids of the edges.
deba@1409
   534
    ///
deba@1409
   535
    /// Returns true if the edgeset can write the ids of the edges.
deba@1409
   536
    /// It is possible only if an "id" named map was written or the 
deba@1409
   537
    /// \c _forceIdMap constructor parameter was true.
deba@1409
   538
    bool isIdWriter() const {
deba@1409
   539
      return forceIdMap || idMap != 0;
deba@1409
   540
    }
deba@1409
   541
deba@1409
   542
    /// \brief Write the id of the given edge.
deba@1409
   543
    ///
deba@1409
   544
    /// It writes the id of the given edge. If there was written an "id"
deba@1409
   545
    /// named map then it will write the map value belongs to the edge.
deba@1409
   546
    /// Otherwise if the \c forceId parameter was true it will write
deba@1409
   547
    /// its id in the graph. 
deba@1409
   548
    void writeId(std::ostream& os, const Item& item) const {
deba@1409
   549
      if (forceIdMap) {
deba@1409
   550
	os << graph.id(item);
deba@1409
   551
      } else {
deba@1409
   552
	idMap->write(os, item);
deba@1409
   553
      }
deba@1409
   554
    } 
deba@1409
   555
deba@1409
   556
  private:
deba@1409
   557
deba@1409
   558
    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
deba@1409
   559
    MapWriters writers;
deba@1409
   560
deba@1409
   561
    WriterBase<Item>* idMap;
deba@1409
   562
    bool forceIdMap;
deba@1409
   563
   
deba@1409
   564
    const Graph& graph;   
deba@1409
   565
    std::string id;
deba@1409
   566
deba@1409
   567
    std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
deba@1409
   568
  };
deba@1409
   569
deba@1409
   570
  /// \ingroup io_group
deba@1409
   571
  /// \brief SectionWriter for writing labeled nodes.
deba@1409
   572
  ///
deba@1409
   573
  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
deba@1409
   574
  /// \c nodes_id may be empty.
deba@1409
   575
  ///
deba@1409
   576
  /// Each line in the section contains the label of the node and 
deba@1409
   577
  /// then the node id. 
deba@1409
   578
  ///
deba@1409
   579
  /// \relates LemonWriter
deba@1409
   580
  template <typename _Graph>
deba@1409
   581
  class NodeWriter : public CommonSectionWriterBase {
deba@1409
   582
    typedef CommonSectionWriterBase Parent;
deba@1409
   583
    typedef _Graph Graph;
deba@1409
   584
    typedef typename Graph::Node Item;
deba@1409
   585
  public:
deba@1409
   586
    
deba@1409
   587
    /// \brief Constructor.
deba@1409
   588
    ///
deba@1409
   589
    /// Constructor for NodeWriter. It creates the NodeWriter and
deba@1409
   590
    /// attach it into the given LemonWriter. The given \c _IdWriter
deba@1409
   591
    /// will write the nodes' id what can be a nodeset writer.
deba@1409
   592
    template <typename _IdWriter>
deba@1409
   593
    NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
deba@1409
   594
	       const std::string& _id = std::string()) 
deba@1409
   595
      : Parent(_writer), id(_id), 
deba@1409
   596
	idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {} 
deba@1409
   597
deba@1409
   598
    /// \brief Destructor.
deba@1409
   599
    ///
deba@1409
   600
    /// Destructor for NodeWriter.
deba@1409
   601
    virtual ~NodeWriter() {}
deba@1409
   602
deba@1409
   603
  private:
deba@1409
   604
    NodeWriter(const NodeWriter&);
deba@1409
   605
    void operator=(const NodeWriter&);
deba@1409
   606
deba@1409
   607
  public:
deba@1409
   608
deba@1409
   609
    /// \brief Add a node writer command for the NodeWriter.
deba@1409
   610
    ///
deba@1409
   611
    /// Add a node writer command for the NodeWriter.
deba@1409
   612
    void writeNode(const std::string& name, const Item& item) {
deba@1409
   613
      writers.push_back(make_pair(name, &item));
deba@1409
   614
    }
deba@1409
   615
deba@1409
   616
  protected:
deba@1409
   617
deba@1409
   618
    /// \brief Header checking function.
deba@1409
   619
    ///
deba@1409
   620
    /// It gives back true when the header line start with \c @nodes,
deba@1409
   621
    /// and the header line's id and the writer's id are the same.
deba@1409
   622
    virtual std::string header() {
deba@1409
   623
      return "@nodes " + id;
deba@1409
   624
    }
deba@1409
   625
deba@1409
   626
    /// \brief  Writer function of the section.
deba@1409
   627
    ///
deba@1409
   628
    /// Write the content of the section.
deba@1409
   629
    virtual void write(std::ostream& os) {
deba@1409
   630
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   631
	os << writers[i].first << ' ';
deba@1409
   632
	idWriter->write(os, *(writers[i].second));
deba@1409
   633
	os << std::endl;
deba@1409
   634
      }
deba@1409
   635
    }
deba@1409
   636
    
deba@1409
   637
  private:
deba@1409
   638
deba@1409
   639
    std::string id;
deba@1409
   640
deba@1409
   641
    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
deba@1409
   642
    ItemWriters writers;
deba@1409
   643
    std::auto_ptr<IdWriterBase<Item> > idWriter;
deba@1409
   644
  };
deba@1409
   645
deba@1409
   646
  /// \ingroup io_group
deba@1409
   647
  /// \brief SectionWriter for writeing labeled edges.
deba@1409
   648
  ///
deba@1409
   649
  /// The edges section's header line is \c \@edges \c edges_id, but the
deba@1409
   650
  /// \c edges_id may be empty.
deba@1409
   651
  ///
deba@1409
   652
  /// Each line in the section contains the label of the edge and 
deba@1409
   653
  /// then the edge id. 
deba@1409
   654
  ///
deba@1409
   655
  /// \relates LemonWriter
deba@1409
   656
  template <typename _Graph>
deba@1409
   657
  class EdgeWriter : public CommonSectionWriterBase {
deba@1409
   658
    typedef CommonSectionWriterBase Parent;
deba@1409
   659
    typedef _Graph Graph;
deba@1409
   660
    typedef typename Graph::Edge Item;
deba@1409
   661
  public:
deba@1409
   662
    
deba@1409
   663
    /// \brief Constructor.
deba@1409
   664
    ///
deba@1409
   665
    /// Constructor for EdgeWriter. It creates the EdgeWriter and
deba@1409
   666
    /// attach it into the given LemonWriter. The given \c _IdWriter
deba@1409
   667
    /// will write the edges' id what can be a edgeset writer.
deba@1409
   668
    template <typename _IdWriter>
deba@1409
   669
    EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
deba@1409
   670
	       const std::string& _id = std::string()) 
deba@1409
   671
      : Parent(_writer), id(_id), 
deba@1409
   672
	idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {} 
deba@1409
   673
deba@1409
   674
    /// \brief Destructor.
deba@1409
   675
    ///
deba@1409
   676
    /// Destructor for EdgeWriter.
deba@1409
   677
    virtual ~EdgeWriter() {}
deba@1409
   678
  private:
deba@1409
   679
    EdgeWriter(const EdgeWriter&);
deba@1409
   680
    void operator=(const EdgeWriter&);
deba@1409
   681
deba@1409
   682
  public:
deba@1409
   683
deba@1409
   684
    /// \brief Add an edge writer command for the NodeWriter.
deba@1409
   685
    ///
deba@1409
   686
    /// Add an edge writer command for the NodeWriter.
deba@1409
   687
    void writeEdge(const std::string& name, const Item& item) {
deba@1409
   688
      writers.push_back(make_pair(name, &item));
deba@1409
   689
    }
deba@1409
   690
deba@1409
   691
  protected:
deba@1409
   692
deba@1409
   693
    /// \brief Header checking function.
deba@1409
   694
    ///
deba@1409
   695
    /// It gives back true when the header line start with \c @nodes,
deba@1409
   696
    /// and the header line's id and the writer's id are the same.
deba@1409
   697
    virtual std::string header() {
deba@1409
   698
      return "@edges " + id;
deba@1409
   699
    }
deba@1409
   700
deba@1409
   701
    /// \brief  Writer function of the section.
deba@1409
   702
    ///
deba@1409
   703
    /// Write the content of the section.
deba@1409
   704
    virtual void write(std::ostream& os) {
deba@1409
   705
      for (int i = 0; i < (int)writers.size(); ++i) {
deba@1409
   706
	os << writers[i].first << ' ';
deba@1409
   707
	idWriter->write(os, *(writers[i].second));
deba@1409
   708
	os << std::endl;
deba@1409
   709
      }
deba@1409
   710
    }
deba@1409
   711
    
deba@1409
   712
  private:
deba@1409
   713
deba@1409
   714
    std::string id;
deba@1409
   715
deba@1409
   716
    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
deba@1409
   717
    ItemWriters writers;
deba@1409
   718
deba@1409
   719
    std::auto_ptr<IdWriterBase<Item> > idWriter;
deba@1409
   720
  };
deba@1409
   721
deba@1409
   722
  /// \ingroup io_group
deba@1409
   723
  /// \brief SectionWriter for attributes.
deba@1409
   724
  ///
deba@1409
   725
  /// The lemon format can store multiple attribute set. Each set has
deba@1409
   726
  /// the header line \c \@attributes \c attributeset_id, but the 
deba@1409
   727
  /// attributeset_id may be empty.
deba@1409
   728
  ///
deba@1409
   729
  /// The attributeset section contains several lines. Each of them starts
deba@1409
   730
  /// with the name of attribute and then the value.
deba@1409
   731
  ///
deba@1409
   732
  /// \relates LemonWriter
deba@1409
   733
  template <typename _Traits = DefaultWriterTraits>
deba@1409
   734
  class AttributeWriter : public CommonSectionWriterBase {
deba@1409
   735
    typedef CommonSectionWriterBase Parent;
deba@1409
   736
    typedef _Traits Traits; 
deba@1409
   737
  public:
deba@1409
   738
    /// \brief Constructor.
deba@1409
   739
    ///
deba@1409
   740
    /// Constructor for AttributeWriter. It creates the AttributeWriter and
deba@1409
   741
    /// attach it into the given LemonWriter.
deba@1409
   742
    AttributeWriter(LemonWriter& _writer, 
deba@1409
   743
		    const std::string& _id = std::string()) 
deba@1409
   744
      : Parent(_writer), id(_id) {}
deba@1409
   745
deba@1409
   746
    /// \brief Destructor.
deba@1409
   747
    ///
deba@1409
   748
    /// Destructor for AttributeWriter.
deba@1409
   749
    virtual ~AttributeWriter() {
deba@1409
   750
      typename Writers::iterator it;
deba@1409
   751
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   752
	delete it->second;
deba@1409
   753
      }
deba@1409
   754
    }
deba@1409
   755
deba@1409
   756
  private:
deba@1409
   757
    AttributeWriter(const AttributeWriter&);
deba@1409
   758
    void operator=(AttributeWriter&);
deba@1409
   759
deba@1409
   760
  public:
deba@1409
   761
    /// \brief Add an attribute writer command for the writer.
deba@1409
   762
    ///
deba@1409
   763
    /// Add an attribute writer command for the writer.
deba@1409
   764
    template <typename Value>
deba@1409
   765
    AttributeWriter& writeAttribute(const std::string& id, 
deba@1409
   766
				    const Value& value) {
deba@1409
   767
      return 
deba@1409
   768
	writeAttribute<typename Traits::template Writer<Value> >(id, value);
deba@1409
   769
    }
deba@1409
   770
deba@1409
   771
    /// \brief Add an attribute writer command for the writer.
deba@1409
   772
    ///
deba@1409
   773
    /// Add an attribute writer command for the writer.
deba@1409
   774
    template <typename Writer, typename Value>
deba@1409
   775
    AttributeWriter& writeAttribute(const std::string& name, 
deba@1409
   776
				    const Value& value,
deba@1409
   777
				    const Writer& writer = Writer()) {
deba@1409
   778
      writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
deba@1409
   779
      			       (value, writer)));
deba@1409
   780
      return *this;
deba@1409
   781
    }
deba@1409
   782
deba@1409
   783
  protected:
deba@1409
   784
deba@1409
   785
    /// \brief The header of section.
deba@1409
   786
    ///
deba@1409
   787
    /// It gives back the header of the section.
deba@1409
   788
    std::string header() {
deba@1409
   789
      return "@attributes " + id;
deba@1409
   790
    }
deba@1409
   791
deba@1409
   792
    /// \brief  Writer function of the section.
deba@1409
   793
    ///
deba@1409
   794
    /// Write the content of the section.
deba@1409
   795
    void write(std::ostream& os) {
deba@1409
   796
      typename Writers::iterator it;
deba@1409
   797
      for (it = writers.begin(); it != writers.end(); ++it) {
deba@1409
   798
	os << it->first << ' ';
deba@1409
   799
	it->second->write(os);
deba@1409
   800
	os << std::endl;
deba@1409
   801
      }
deba@1409
   802
    }    
deba@1409
   803
deba@1409
   804
  private:
deba@1409
   805
    std::string id;
deba@1409
   806
deba@1409
   807
    typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
deba@1409
   808
    Writers writers;  
deba@1409
   809
  };
deba@1409
   810
deba@1409
   811
deba@1409
   812
}
deba@1409
   813
#endif