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