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