Index: molecuilder/src/Descriptors/AtomDescriptor.cpp
===================================================================
--- molecuilder/src/Descriptors/AtomDescriptor.cpp	(revision 86b9172421385fb0be15c2d52e42bca451d0ba6e)
+++ molecuilder/src/Descriptors/AtomDescriptor.cpp	(revision 973c03ed6d3520b9b4b144344659c24866f3c0f4)
@@ -11,4 +11,5 @@
 
 #include <boost/bind.hpp>
+#include <cassert>
 
 using namespace std;
@@ -19,4 +20,7 @@
 AtomDescriptor::AtomDescriptor()
 {
+}
+
+AtomDescriptor::AtomDescriptor(const AtomDescriptor &desc) {
 }
 
@@ -30,19 +34,11 @@
 }
 
-AtomPredicateDescriptor::AtomPredicateDescriptor()
-{
-}
-
-AtomPredicateDescriptor::~AtomPredicateDescriptor()
-{
-}
-
-atom* AtomPredicateDescriptor::find() {
+atom* AtomDescriptor::find() {
   atoms_t atoms = getAtoms();
-  atoms_iter_t res = find_if(atoms.begin(),atoms.end(),boost::bind(&AtomPredicateDescriptor::predicate,this,_1));
+  atoms_iter_t res = find_if(atoms.begin(),atoms.end(),boost::bind(&AtomDescriptor::predicate,this,_1));
   return (res!=atoms.end())?((*res).second):0;
 }
 
-vector<atom*> AtomPredicateDescriptor::findAll() {
+vector<atom*> AtomDescriptor::findAll() {
   vector<atom*> res;
   atoms_t atoms = getAtoms();
@@ -53,2 +49,109 @@
   }
 }
+
+// stuff for operators
+
+// AND
+AtomAndDescriptor::AtomAndDescriptor(const AtomDescriptor &_lhs,const AtomDescriptor &_rhs){
+  lhs=_lhs.clone();
+  rhs=_rhs.clone();
+}
+
+AtomAndDescriptor::AtomAndDescriptor(const AtomAndDescriptor &_desc)
+{
+  // the copy constructor needs it's parameter as const to work,
+  // however we need to be able to transfer the ownership of the pointers
+  // to the new method to avoid another cloning.
+  //
+  // the only place where the copy constructor is used for these classes,
+  // is when returning a temporary.
+  // this is one of the very rare cases when const_cast makes sense
+  AtomAndDescriptor &desc = const_cast<AtomAndDescriptor&>(_desc);
+  lhs = desc.lhs;
+  rhs = desc.rhs;
+}
+
+AtomAndDescriptor::~AtomAndDescriptor(){
+}
+
+bool AtomAndDescriptor::predicate(std::pair<int,atom*> atom){
+  return lhs->predicate(atom) && rhs->predicate(atom);
+}
+
+AtomAndDescriptor::desc_ptr AtomAndDescriptor::clone() const{
+  return desc_ptr(new AtomAndDescriptor(*lhs,*rhs));
+}
+
+AtomAndDescriptor operator&&(const AtomDescriptor &lhs, const AtomDescriptor &rhs){
+  return AtomAndDescriptor(lhs,rhs);
+}
+
+// OR
+
+AtomOrDescriptor::AtomOrDescriptor(const AtomDescriptor &_lhs,const AtomDescriptor &_rhs){
+  lhs=_lhs.clone();
+  rhs=_rhs.clone();
+}
+
+AtomOrDescriptor::AtomOrDescriptor(const AtomOrDescriptor &_desc)
+{
+  // the copy constructor needs it's parameter as const to work,
+  // however we need to be able to transfer the ownership of the pointers
+  // to the new method to avoid another cloning.
+  //
+  // the only place where the copy constructor is used for these classes,
+  // is when returning a temporary.
+  // this is one of the very rare cases when const_cast makes sense
+  AtomOrDescriptor &desc = const_cast<AtomOrDescriptor&>(_desc);
+  lhs = desc.lhs;
+  rhs = desc.rhs;
+}
+
+AtomOrDescriptor::~AtomOrDescriptor(){
+}
+
+bool AtomOrDescriptor::predicate(std::pair<int,atom*> atom){
+  return lhs->predicate(atom) || rhs->predicate(atom);
+}
+
+AtomAndDescriptor::desc_ptr AtomOrDescriptor::clone() const{
+  return desc_ptr(new AtomOrDescriptor(*lhs,*rhs));
+}
+
+AtomOrDescriptor  operator||(const AtomDescriptor &lhs, const AtomDescriptor &rhs){
+  return AtomOrDescriptor(lhs,rhs);
+}
+
+// NOT
+
+AtomNotDescriptor::AtomNotDescriptor(const AtomDescriptor &_arg){
+  arg = _arg.clone();
+}
+
+AtomNotDescriptor::AtomNotDescriptor(const AtomNotDescriptor &_desc) {
+  // the copy constructor needs it's parameter as const to work,
+  // however we need to be able to transfer the ownership of the pointers
+  // to the new method to avoid another cloning.
+  //
+  // the only place where the copy constructor is used for these classes,
+  // is when returning a temporary.
+  // this is one of the very rare cases when const_cast makes sense
+  AtomNotDescriptor &desc = const_cast<AtomNotDescriptor&>(_desc);
+  arg = desc.arg;
+}
+
+AtomNotDescriptor::~AtomNotDescriptor()
+{
+}
+
+bool AtomNotDescriptor::predicate(std::pair<int,atom*> atom){
+ return !(arg->predicate(atom));
+}
+
+AtomAndDescriptor::desc_ptr AtomNotDescriptor::clone() const{
+  return desc_ptr(new AtomNotDescriptor(*arg));
+}
+
+AtomNotDescriptor operator!(const AtomDescriptor &arg){
+  return AtomNotDescriptor(arg);
+}
Index: molecuilder/src/Descriptors/AtomDescriptor.hpp
===================================================================
--- molecuilder/src/Descriptors/AtomDescriptor.hpp	(revision 86b9172421385fb0be15c2d52e42bca451d0ba6e)
+++ molecuilder/src/Descriptors/AtomDescriptor.hpp	(revision 973c03ed6d3520b9b4b144344659c24866f3c0f4)
@@ -9,6 +9,8 @@
 #define ATOMDESCRIPTOR_HPP_
 
-#include<vector>
-#include<map>
+
+#include <vector>
+#include <map>
+#include <boost/shared_ptr.hpp>
 #include "World.hpp"
 
@@ -18,4 +20,7 @@
 {
 public:
+
+  typedef boost::shared_ptr<AtomDescriptor> desc_ptr;
+
   friend atom* World::getAtom(AtomDescriptor& descriptor);
   friend std::vector<atom*> World::getAllAtoms(AtomDescriptor& descriptor);
@@ -23,21 +28,73 @@
   AtomDescriptor();
   virtual ~AtomDescriptor();
+  AtomDescriptor(const AtomDescriptor&);
+
+  virtual bool predicate(std::pair<int,atom*>)=0;
+  // clone is only used internally to generate operators
+  virtual desc_ptr clone() const=0;
 
 protected:
-  virtual atom* find()=0;
-  virtual std::vector<atom*> findAll()=0;
+  virtual atom* find();
+  virtual std::vector<atom*> findAll();
   std::map<int,atom*>& getAtoms();
 };
 
-class AtomPredicateDescriptor : public AtomDescriptor{
+class AtomAndDescriptor : public AtomDescriptor
+{
+  friend AtomAndDescriptor operator&&(const AtomDescriptor &lhs, const AtomDescriptor &rhs);
 public:
-  AtomPredicateDescriptor();
-  virtual ~AtomPredicateDescriptor();
+  AtomAndDescriptor(const AtomAndDescriptor&);
+  ~AtomAndDescriptor();
 
-protected:
-  virtual atom *find();
-  virtual std::vector<atom*> findAll();
-  virtual bool predicate(std::pair<int,atom*>)=0;
+  virtual desc_ptr clone() const;
+  virtual bool predicate(std::pair<int,atom*>);
+
+private:
+  desc_ptr lhs;
+  desc_ptr rhs;
+
+  // private constructor to enforce construction through operators
+  AtomAndDescriptor(const AtomDescriptor &_lhs, const AtomDescriptor &_rhs);
 };
 
+class AtomOrDescriptor : public AtomDescriptor
+{
+  friend AtomOrDescriptor  operator||(const AtomDescriptor &lhs, const AtomDescriptor &rhs);
+public:
+  AtomOrDescriptor(const AtomOrDescriptor &);
+  ~AtomOrDescriptor();
+
+  virtual desc_ptr clone() const;
+  virtual bool predicate(std::pair<int,atom*>);
+
+private:
+  desc_ptr lhs;
+  desc_ptr rhs;
+
+  // private constructor to enforce construction through operators
+  AtomOrDescriptor(const AtomDescriptor &_lhs, const AtomDescriptor &_rhs);
+};
+
+class AtomNotDescriptor : public AtomDescriptor
+{
+  friend AtomNotDescriptor operator!(const AtomDescriptor &arg);
+public:
+  AtomNotDescriptor(const AtomNotDescriptor &);
+  ~AtomNotDescriptor();
+
+  virtual desc_ptr clone() const;
+  virtual bool predicate(std::pair<int,atom*>);
+
+private:
+  desc_ptr arg;
+
+  // protected constructor to enforce construction through operators
+  AtomNotDescriptor(const AtomDescriptor &_arg);
+};
+
+// no true short circuit, but the test of the second descriptor wont be done
+AtomAndDescriptor operator&&(const AtomDescriptor &lhs, const AtomDescriptor &rhs);
+AtomOrDescriptor  operator||(const AtomDescriptor &lhs, const AtomDescriptor &rhs);
+AtomNotDescriptor operator!(const AtomDescriptor &arg);
+
 #endif /* ATOMDESCRIPTOR_HPP_ */
Index: molecuilder/src/Descriptors/AtomIdDescriptor.cpp
===================================================================
--- molecuilder/src/Descriptors/AtomIdDescriptor.cpp	(revision 86b9172421385fb0be15c2d52e42bca451d0ba6e)
+++ molecuilder/src/Descriptors/AtomIdDescriptor.cpp	(revision 973c03ed6d3520b9b4b144344659c24866f3c0f4)
@@ -19,4 +19,16 @@
 {}
 
+bool AtomIdDescriptor::predicate(std::pair<int,atom*> atom) {
+  return atom.second->getId()==id;
+}
+
+AtomDescriptor::desc_ptr AtomIdDescriptor::clone() const{
+  return desc_ptr(new AtomIdDescriptor(id));
+}
+
+#if 0
+
+// so far the lookuptable for Atoms-by-id does not work, since atoms don't get an ID upon creation.
+// instead of this we rely on walking through all atoms.
 
 atom *AtomIdDescriptor::find(){
@@ -30,2 +42,4 @@
   return (res)?(vector<atom*>(1,res)):(vector<atom*>());
 }
+
+#endif
Index: molecuilder/src/Descriptors/AtomIdDescriptor.hpp
===================================================================
--- molecuilder/src/Descriptors/AtomIdDescriptor.hpp	(revision 86b9172421385fb0be15c2d52e42bca451d0ba6e)
+++ molecuilder/src/Descriptors/AtomIdDescriptor.hpp	(revision 973c03ed6d3520b9b4b144344659c24866f3c0f4)
@@ -17,8 +17,13 @@
   virtual ~AtomIdDescriptor();
 
+  bool predicate(std::pair<int,atom*> atom);
+
+  virtual desc_ptr clone() const;
+
 protected:
+#if 0
   atom *find();
   std::vector<atom*> findAll();
-
+#endif
 private:
   int id;
