Index: src/Fragmentation/Exporters/HydrogenPool.cpp
===================================================================
--- src/Fragmentation/Exporters/HydrogenPool.cpp	(revision c3df2354750ff648d82e55250da81445e260d5f0)
+++ src/Fragmentation/Exporters/HydrogenPool.cpp	(revision c3df2354750ff648d82e55250da81445e260d5f0)
@@ -0,0 +1,138 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2013 University of Bonn. All rights reserved.
+ * 
+ *
+ *   This file is part of MoleCuilder.
+ *
+ *    MoleCuilder is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    MoleCuilder is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with MoleCuilder.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * HydrogenPool.cpp
+ *
+ *  Created on: Mar 3, 2013
+ *      Author: heber
+ */
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "CodePatterns/MemDebug.hpp"
+
+#include "HydrogenPool.hpp"
+
+#include "CodePatterns/Assert.hpp"
+#include "CodePatterns/Log.hpp"
+
+#include "Atom/atom.hpp"
+#include "Atom/AtomObserver.hpp"
+#include "Descriptors/AtomIdDescriptor.hpp"
+#include "Element/periodentafel.hpp"
+#include "World.hpp"
+
+HydrogenPool::HydrogenPool() :
+    HydrogenCount(0)
+{}
+
+HydrogenPool::~HydrogenPool()
+{
+  cleanup();
+}
+
+void HydrogenPool::requestHydrogenIntoPool()
+{
+  // get new hydrogen from world, but remove its observers
+  atom * const Walker = World::getInstance().createAtom();
+  Walker->setType(HYDROGEN);  // set element
+  Walker->setName(std::string("H_")+toString(HydrogenCount));
+  Walker->signOff(AtomObserver::getPointer(), AtomObservable::PositionChanged);
+  Walker->signOff(AtomObserver::getPointer(), AtomObservable::ElementChanged);
+  HydrogenQueue.push_back(Walker);
+  ++HydrogenCount;
+
+  // give warning if pool has more than thereshold
+  if (HydrogenCount >= WARNINGTHRESHOLD) {
+    ELOG(2, "HydrogenPool contains more hydrogen atoms than limit.");
+    ELOG(2, "Either someone requesting too eagerly, or another not returning them.");
+  }
+
+  // final check
+  ASSERT(!HydrogenQueue.empty(),
+      "HydrogenPool::requestHydrogenIntoPool() - failed to request more hydrogens.");
+}
+
+atom * HydrogenPool::leaseHydrogen()
+{
+  // check the queue, if empty, add more hydrogens
+  if (HydrogenQueue.empty())
+    requestHydrogenIntoPool();
+
+  // pop hydrogen, mark down, and deliver
+  atom * const Walker = HydrogenQueue.front();
+  ASSERT( HydrogenInUse.count(Walker->getId()) == 0,
+      "HydrogenPool::leaseHydrogen() - hydrogen "+toString(*Walker)
+      +" from pool is already in use.");
+  LOG(3, "DEBUG: Leasing " << *Walker << ".");
+  HydrogenInUse.insert( std::make_pair( Walker->getId(), Walker) );
+  HydrogenQueue.pop_front();
+  return Walker;
+}
+
+void HydrogenPool::releaseHydrogen(atom * _atom)
+{
+  if (_atom == NULL) {
+    ASSERT( 0,
+        "HydrogenPool::releaseHydrogen() - got NULL atom.");
+    return;
+  }
+
+  // check that it is marked down
+  {
+    HydrogenInUse_t::iterator iter = HydrogenInUse.find(_atom->getId());
+    if (iter == HydrogenInUse.end()) {
+      ASSERT( 0,
+          "HydrogenPool::releaseHydrogen() - got unknown atom "+toString(_atom)+".");
+      return;
+    }
+    LOG(3, "DEBUG: Releasing " << *_atom << ".");
+    HydrogenInUse.erase(iter);
+  }
+  // check into queue
+  HydrogenQueue.push_back(_atom);
+}
+
+void HydrogenPool::releaseHydrogen(atomId_t _atom)
+{
+  atom * const Walker = World::getInstance().getAtom(AtomById(_atom));
+  ASSERT( Walker != NULL,
+      "HydrogenPool::releaseHydrogen() - id "
+      +toString(_atom)+" unknown to World.");
+  releaseHydrogen(Walker);
+}
+
+void HydrogenPool::cleanup()
+{
+  ASSERT(HydrogenInUse.empty(),
+      "HydrogenPool::cleanup() - cleanup called, but still hydrogens in use.");
+  for (HydrogenQueue_t::iterator iter = HydrogenQueue.begin();
+      !HydrogenQueue.empty(); iter = HydrogenQueue.begin()) {
+    atom * const Walker = *iter;
+    HydrogenQueue.erase(iter);
+    World::getInstance().destroyAtom(Walker);
+  }
+}
Index: src/Fragmentation/Exporters/HydrogenPool.hpp
===================================================================
--- src/Fragmentation/Exporters/HydrogenPool.hpp	(revision c3df2354750ff648d82e55250da81445e260d5f0)
+++ src/Fragmentation/Exporters/HydrogenPool.hpp	(revision c3df2354750ff648d82e55250da81445e260d5f0)
@@ -0,0 +1,92 @@
+/*
+ * HydrogenPool.hpp
+ *
+ *  Created on: Mar 3, 2013
+ *      Author: heber
+ */
+
+#ifndef HYDROGENPOOL_HPP_
+#define HYDROGENPOOL_HPP_
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <deque>
+#include <map>
+
+#include "types.hpp"
+
+class atom;
+
+/** This class contains a pool of hydrogen meant for saturation.
+ *
+ * These hydrogen atoms do not trigger any updates, they are mostly
+ * invisible to the system.
+ *
+ * If the pool is lacking hydrogens, it requests more from the World.
+ *
+ * The idea is that we always create a single fragment, saturate it with
+ * hydrogen atoms from the pool, then store it to file or convert to a
+ * job. Directly afterwards, the fragment is free'd and the hydrogen may
+ * go back into the pool.
+ */
+class HydrogenPool
+{
+  //!> grant unit test access to private parts
+  friend class HydrogenPoolTest;
+public:
+  HydrogenPool();
+  ~HydrogenPool();
+
+  /** Delivers a hydrogen atom for use.
+   *
+   * \return point to the hydrogen atom
+   */
+  atom * leaseHydrogen();
+
+  /** Releases a used hydrogen again.
+   *
+   * \param _atom hydrogen atom to release
+   */
+  void releaseHydrogen(atom * _atom);
+
+  /** Releases a used hydrogen again.
+   *
+   * \param _atom hydrogen atom to release
+   */
+  void releaseHydrogen(atomId_t _atom);
+
+  //!> enum to define the atomic number of atoms contained in the pool
+  enum { HYDROGEN = 1 };
+
+private:
+  /** Requests a hydrogen atom from the World and places it into the queue.
+   *
+   */
+  void requestHydrogenIntoPool();
+
+  /** Helper function that removes all present hydrogen atoms again.
+   *
+   */
+  void cleanup();
+
+private:
+  //!> typedef for the deque of available hydrogens.
+  typedef std::deque<atom *> HydrogenQueue_t;
+  //!> typedef for the map of all hydrogens currently in use in a fragment.
+  typedef std::map<atomId_t, atom *> HydrogenInUse_t;
+
+  //!> enum to define a warning constant for the limit of hydrogens
+  enum { WARNINGTHRESHOLD = 100 };
+
+  //!> counter for the total number of hydrogens requested so far.
+  int HydrogenCount;
+  //!> Queue of available hydrogen atoms
+  HydrogenQueue_t HydrogenQueue;
+  //!> Map for looking up ids of hydrogen in use for reinsertion into queue
+  HydrogenInUse_t HydrogenInUse;
+};
+
+#endif /* HYDROGENPOOL_HPP_ */
Index: src/Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.cpp
===================================================================
--- src/Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.cpp	(revision c3df2354750ff648d82e55250da81445e260d5f0)
+++ src/Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.cpp	(revision c3df2354750ff648d82e55250da81445e260d5f0)
@@ -0,0 +1,152 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2013 University of Bonn. All rights reserved.
+ * 
+ *
+ *   This file is part of MoleCuilder.
+ *
+ *    MoleCuilder is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    MoleCuilder is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with MoleCuilder.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * HydrogenPoolUnitTest.cpp
+ *
+ *  Created on: Mar 03, 2013
+ *      Author: heber
+ */
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+using namespace std;
+
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+// include headers that implement a archive in simple text format
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+
+#include "HydrogenPoolUnitTest.hpp"
+
+#include "CodePatterns/Assert.hpp"
+
+#include "Fragmentation/Exporters/HydrogenPool.hpp"
+#include "World.hpp"
+
+#ifdef HAVE_TESTRUNNER
+#include "UnitTestMain.hpp"
+#endif /*HAVE_TESTRUNNER*/
+
+/********************************************** Test classes **************************************/
+
+// Registers the fixture into the 'registry'
+CPPUNIT_TEST_SUITE_REGISTRATION( HydrogenPoolTest );
+
+
+void HydrogenPoolTest::setUp()
+{
+  // failing asserts should be thrown
+  ASSERT_DO(Assert::Throw);
+
+  pool = new HydrogenPool();
+}
+
+
+void HydrogenPoolTest::tearDown()
+{
+  delete pool;
+
+  World::purgeInstance();
+}
+
+/** UnitTest for leaseHydrogen() and releaseHydrogen.
+ */
+void HydrogenPoolTest::lease_releaseHydrogen_Test()
+{
+  // check simple test
+  {
+    CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+    atom * const Walker = pool->leaseHydrogen();
+    CPPUNIT_ASSERT( pool->HydrogenQueue.empty() );
+    CPPUNIT_ASSERT( !pool->HydrogenInUse.empty() );
+    CPPUNIT_ASSERT_EQUAL( 1, World::getInstance().numAtoms() );
+    pool->releaseHydrogen(Walker);
+    CPPUNIT_ASSERT( !pool->HydrogenQueue.empty() );
+    CPPUNIT_ASSERT( pool->HydrogenInUse.empty() );
+    pool->cleanup();
+    CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+  }
+  // check via id test
+  {
+    CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+    atom * const Walker = pool->leaseHydrogen();
+    CPPUNIT_ASSERT( pool->HydrogenQueue.empty() );
+    CPPUNIT_ASSERT( !pool->HydrogenInUse.empty() );
+    CPPUNIT_ASSERT_EQUAL( 1, World::getInstance().numAtoms() );
+    pool->releaseHydrogen(Walker->getId());
+    CPPUNIT_ASSERT( !pool->HydrogenQueue.empty() );
+    CPPUNIT_ASSERT( pool->HydrogenInUse.empty() );
+    pool->cleanup();
+    CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+  }
+  // check that can't cleanup with leased atoms
+  {
+    CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+    atom * const Walker = pool->leaseHydrogen();
+    std::cerr << "The following assertion is intended and does not entail a failure of the test." << std::endl;
+#ifndef NDEBUG
+    CPPUNIT_ASSERT_THROW(pool->cleanup(), Assert::AssertionFailure );
+#else
+    pool->cleanup();
+#endif
+    CPPUNIT_ASSERT_EQUAL( 1, World::getInstance().numAtoms() );
+    pool->releaseHydrogen(Walker);
+    pool->cleanup();
+    CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+  }
+  // check returning from atom
+  {
+    CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+    atom * const Walker = pool->leaseHydrogen();
+    CPPUNIT_ASSERT_EQUAL( 1, World::getInstance().numAtoms() );
+    atom * const InvalidWalker = NULL;
+    std::cerr << "The following assertion is intended and does not entail a failure of the test." << std::endl;
+#ifndef NDEBUG
+    CPPUNIT_ASSERT_THROW(pool->releaseHydrogen(InvalidWalker), Assert::AssertionFailure );
+#else
+    pool->releaseHydrogen(InvalidWalker);
+#endif
+    CPPUNIT_ASSERT_EQUAL( 1, World::getInstance().numAtoms() );
+    pool->releaseHydrogen(Walker);
+    pool->cleanup();
+    CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+  }
+}
+
+/** UnitTest for requestHydrogen().
+ */
+void HydrogenPoolTest::requestHydrogen_Test()
+{
+  CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+  pool->requestHydrogenIntoPool();
+  CPPUNIT_ASSERT( !pool->HydrogenQueue.empty() );
+  CPPUNIT_ASSERT_EQUAL( 1, World::getInstance().numAtoms() );
+  pool->cleanup();
+  CPPUNIT_ASSERT_EQUAL( 0, World::getInstance().numAtoms() );
+}
Index: src/Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.hpp
===================================================================
--- src/Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.hpp	(revision c3df2354750ff648d82e55250da81445e260d5f0)
+++ src/Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.hpp	(revision c3df2354750ff648d82e55250da81445e260d5f0)
@@ -0,0 +1,40 @@
+/*
+ * HydrogenPoolUnitTest.hpp
+ *
+ *  Created on: Aug 09, 2012
+ *      Author: heber
+ */
+
+#ifndef HYDROGENPOOLUNITTEST_HPP_
+#define HYDROGENPOOLUNITTEST_HPP_
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class HydrogenPool;
+
+/********************************************** Test classes **************************************/
+
+class HydrogenPoolTest : public CppUnit::TestFixture
+{
+    CPPUNIT_TEST_SUITE( HydrogenPoolTest) ;
+    CPPUNIT_TEST ( lease_releaseHydrogen_Test );
+    CPPUNIT_TEST ( requestHydrogen_Test );
+    CPPUNIT_TEST_SUITE_END();
+
+public:
+      void setUp();
+      void tearDown();
+      void lease_releaseHydrogen_Test();
+      void requestHydrogen_Test();
+
+private:
+      HydrogenPool *pool;
+};
+
+#endif /* HYDROGENPOOLUNITTEST_HPP_ */
Index: src/Fragmentation/Exporters/unittests/Makefile.am
===================================================================
--- src/Fragmentation/Exporters/unittests/Makefile.am	(revision c3df2354750ff648d82e55250da81445e260d5f0)
+++ src/Fragmentation/Exporters/unittests/Makefile.am	(revision c3df2354750ff648d82e55250da81445e260d5f0)
@@ -0,0 +1,30 @@
+# PLEASE adhere to the alphabetical ordering in this Makefile!
+# Also indentation by a single tab
+
+FRAGMENTATIONEXPORTERSSOURCES = \
+	../Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.cpp
+
+FRAGMENTATIONEXPORTERSTESTSHEADERS = \
+	../Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.hpp
+
+FRAGMENTATIONEXPORTERSTESTS = \
+	HydrogenPoolUnitTest
+
+TESTS += $(FRAGMENTATIONEXPORTERSTESTS)
+check_PROGRAMS += $(FRAGMENTATIONEXPORTERSTESTS) 
+noinst_PROGRAMS += $(FRAGMENTATIONEXPORTERSTESTS)
+
+FRAGMENTATIONEXPORTERSLIBS = \
+	../libMolecuilderFragmentation.la \
+	${CodePatterns_LIBS} \
+	$(BOOST_LIB)
+
+HydrogenPoolUnitTest_SOURCES = $(top_srcdir)/src/unittests/UnitTestMain.cpp \
+	../Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.cpp \
+	../Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.hpp
+HydrogenPoolUnitTest_LDADD = \
+	${FRAGMENTATIONEXPORTERSLIBS} \
+	../libMolecuilderUI.la
+
+
+#AUTOMAKE_OPTIONS = parallel-tests
Index: src/Fragmentation/Makefile.am
===================================================================
--- src/Fragmentation/Makefile.am	(revision 8652a307767040601be3b17560eef6939d7116f3)
+++ src/Fragmentation/Makefile.am	(revision c3df2354750ff648d82e55250da81445e260d5f0)
@@ -5,4 +5,5 @@
 	Fragmentation/Exporters/ExportGraph_ToFiles.cpp \
 	Fragmentation/Exporters/ExportGraph.cpp \
+	Fragmentation/Exporters/HydrogenPool.cpp \
 	Fragmentation/Homology/FragmentEdge.cpp \
 	Fragmentation/Homology/FragmentNode.cpp \
@@ -28,4 +29,5 @@
 	Fragmentation/Exporters/ExportGraph_ToFiles.hpp \
 	Fragmentation/Exporters/ExportGraph.hpp \
+	Fragmentation/Exporters/HydrogenPool.hpp \
 	Fragmentation/Homology/FragmentEdge.hpp \
 	Fragmentation/Homology/FragmentNode.hpp \
