lemon/lemon_writer.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1690 7db44a7ab939
child 1845 f8bbfed86036
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
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