diff --git sites/all/modules/custom/cnr/corresponding_node_references.crud.inc sites/all/modules/custom/cnr/corresponding_node_references.crud.inc
new file mode 100644
index 0000000..89ea1db
--- /dev/null
+++ sites/all/modules/custom/cnr/corresponding_node_references.crud.inc
@@ -0,0 +1,159 @@
+<?php
+// $Id: $
+
+/**
+ * @file
+ * Include file providing corresponding node reference insert, update, and delete handling.
+ */
+
+/** 
+ * Add any corresponding references on node insertion.
+ * 
+ * @param $home_node the node object catched in the node api on this node a reference is made to the away node
+ * @param $home_field the field on the home node used to make the reference
+ * @param $away_node_type the type of the away node
+ * @param $away_field the name of the field on the away node referencing to the home node
+ *  
+ */
+function corresponding_node_references_insert($home_node, $home_field, $away_node_type, $away_field) {
+  $old_node = node_load($home_node->nid);
+
+  // Determine the nodereference values after the insert.
+  if (isset($home_node->$home_field) && is_array($home_node->$home_field)) {
+    foreach ($home_node->$home_field as $reference) {
+      if (!empty($reference['nid'])) {
+        // Load the referenced node if it is of the specified away type.
+        if ($referenced_node = node_load(array('nid' => $reference['nid'], 'type' => $away_node_type))) {
+          // Add the new reference.
+          $referenced_node->{$away_field}[] = array('nid' => $home_node->nid);
+          _corresponding_node_references_update($referenced_node, $away_field);
+        }
+      }
+    }
+  }
+}
+
+/** 
+ * Change corresponding references on node updating.
+ *
+ * Corresponding changes are made for any references removed or added.
+ * 
+ * @param $home_node the node object catched in the node api on this node a reference is made to the away node
+ * @param $home_field the field on the home node used to make the reference
+ * @param $away_node_type the type of the away node
+ * @param $away_field the name of the field on the away node referencing to the home node
+ *  
+ */
+function corresponding_node_references_update($home_node, $home_field, $away_node_type, $away_field) {
+  $old_node = node_load($home_node->nid);
+  $old = $new = array();
+
+  if ($home_node->$home_field != $old_node->$home_field) {
+    // Determine the nodereference values before the update.
+    if (isset($old_node->$home_field) && is_array($old_node->$home_field)) {
+      foreach ($old_node->$home_field as $reference) {
+        if (!empty($reference['nid'])) {
+          $old[] = $reference['nid'];
+        }
+      }
+    }
+    // Determine the nodereference values after the update.
+    if (isset($home_node->$home_field) && is_array($home_node->$home_field)) {
+      foreach ($home_node->$home_field as $reference) {
+        if (!empty($reference['nid'])) {
+          $new[] = $reference['nid'];
+        }
+      }
+    }
+    // Handle removed references.
+    if ($removed = array_diff($old, $new)) {
+      foreach ($removed as $nid) {
+        // Load the referenced node if it is of the specified away type.
+        if ($referenced_node = node_load(array('nid' => $nid, 'type' => $away_node_type))) {
+          if (isset($referenced_node->$away_field) && is_array($referenced_node->$away_field)) {
+            // Iterate through the away node's references.
+            foreach ($referenced_node->$away_field as $key => $value) {
+              // Remove references to the deleted node.
+              if ($value['nid'] && $value['nid'] == $home_node->nid) {
+                unset($referenced_node->{$away_field}[$key]);
+                _corresponding_node_references_update($referenced_node, $away_field);
+                break;             
+              }
+            }
+          }
+        }
+      }
+    }
+    // Handle added references.
+    if ($added = array_diff($new, $old)) {
+      foreach ($added as $nid) {
+        // Load the referenced node if it is of the specified away type.
+        if ($referenced_node = node_load(array('nid' => $nid, 'type' => $away_node_type))) {
+          // Detect whether the reference already exists.
+          $exists = FALSE;
+          if ($referenced_node->$away_field && !empty($referenced_node->$away_field)) {
+            foreach ($referenced_node->$away_field as $data) {
+              if ($data['nid'] == $home_node->nid) {
+                $exists = TRUE;
+                break;
+              }
+            }
+          }
+          // Add the new reference. Don't create a duplicate.
+          if (!$exists) {
+            $referenced_node->{$away_field}[] = array('nid' => $home_node->nid);
+            _corresponding_node_references_update($referenced_node, $away_field);
+          }
+        }
+      }
+    }
+  }
+}
+
+/** 
+ * Remove corresponding references on node deletion.
+ * 
+ * @param $home_node the node object catched in the node api on this node a reference is made to the away node
+ * @param $home_field the field on the home node used to make the reference
+ * @param $away_node_type the type of the away node
+ * @param $away_field the name of the field on the away node referencing to the home node
+ *  
+ */
+function corresponding_node_references_delete($home_node, $home_field, $away_node_type, $away_field) {
+  // Iterate through the field's references.
+  foreach ($home_node->$home_field as $reference) {
+    if (!empty($reference['nid'])) {
+      // Load the referenced node if it is of the specified away type.
+      if ($referenced_node = node_load(array('nid' => $nid, 'type' => $away_node_type))) {
+        // Iterate through the away node's references.
+        foreach ($referenced_node->$away_field as $key => $value) {
+          // Remove references to the deleted node.
+          if ($value['nid'] && $value['nid'] == $home_node->nid) {
+            unset($referenced_node->{$away_field}[$key]);
+            _corresponding_node_references_update($referenced_node, $away_field);
+            break;             
+          }
+        }
+      }
+    }
+  }
+}
+
+/** 
+ * Update field data.
+ * 
+ * @param $referenced_node the referenced node to be updated
+ * @param $away_field the field on the referenced node used to make the reference
+ *  
+ */
+function _corresponding_node_references_update($referenced_node, $away_field) {
+  // Create a version of the node with just the minimum data needed.
+  // By doing so, we avoid triggering unneeded operations.
+  $ref = new StdClass();
+  // nid, vid, type, and the field we're operating on are the minimum requirements.
+  foreach (array('nid', 'vid', 'type', $away_field) as $field_name) {
+    $ref->$field_name = $referenced_node->$field_name;
+  }
+  // Call content module's update function.
+  content_update($ref);
+}
diff --git sites/all/modules/custom/cnr/corresponding_node_references.module sites/all/modules/custom/cnr/corresponding_node_references.module
index 770121d..c47cf3d 100644
--- sites/all/modules/custom/cnr/corresponding_node_references.module
+++ sites/all/modules/custom/cnr/corresponding_node_references.module
@@ -147,141 +147,36 @@ function corresponding_node_references_format_label($key) {
  * Implementation of hook_nodeapi()
  */
 function corresponding_node_references_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
-  //the hook wont be executed when not updating, deleting or inserting
-  if (!($op == 'delete' || $op == 'update' || $op == 'insert' )) { 
-    return; 
-  }
-  $result = db_query("SELECT node_types_content_fields FROM {corresponding_node_references} WHERE enabled = %d", 1);
+
   switch ($op) {
-    case delete:
-      while ($row = db_fetch_object($result)) {
-        $key = explode('*', $row->node_types_content_fields);
-        switch ($node->type) {
-          case $key[0]:
-            corresponding_node_references_remove_node_refs_after_delete($node->nid, $key[3].'_nid', 'content_'.$key[3]);
-            break;
-          case $key[2]:
-            corresponding_node_references_remove_node_refs_after_delete($node->nid, $key[1].'_nid', 'content_'.$key[1]);      
-            break;
-        }
-      }
-      break;
+    case insert:  
     case update:
-    case insert:      
+    case delete:
+      module_load_include('inc', 'corresponding_node_references', 'corresponding_node_references.crud');
+
+      $result = db_query("SELECT node_types_content_fields FROM {corresponding_node_references} WHERE enabled = %d", 1);
       while ($row = db_fetch_object($result)) {
         $key = explode('*', $row->node_types_content_fields);
         
         switch ($node->type) {
           case $key[0]:
-            $home_node = $node;
-            $home_field = $key[1];
-            $away_node_type = $key[2];
-            $away_field = $key[3];
-            corresponding_node_references_set_reverse_reference($home_node, $home_field, $away_node_type, $away_field);
+            $args = array($node, $key[1], $key[2], $key[3]);
+            $function = 'corresponding_node_references_' . $op;
+            call_user_func_array($function, $args);
             if ($key[0] != $key[2]) { 
               break;
             }
+            // Fall through.
           case $key[2]:
-            $home_node = $node;
-            $home_field = $key[3];
-            $away_node_type = $key[0];
-            $away_field = $key[1];
-            corresponding_node_references_set_reverse_reference($home_node, $home_field, $away_node_type, $away_field);           
+            $args = array($node, $key[3], $key[0], $key[1]);
+            $function = 'corresponding_node_references_' . $op;
+            call_user_func_array($function, $args);
             break;
         }
       }
       break;
   }
 }
-/** 
- * Executes functions excuting queries to set the node reference on the away node to the home node
- * 
- * @param $home_node the node object catched in the node api on this node a reference is made to the away node
- * @param $home_field the field on the home node used to make the reference
- * @param $away_node_type the type of the away node
- * @param $away_field the name of the field on the away node referencing to the home node
- *  
- */
-function corresponding_node_references_set_reverse_reference($home_node, $home_field, $away_node_type, $away_field) {
-  $home_table = 'content_'.$home_field;
-  $away_table = 'content_'.$away_field;
- 
-  $referenced_nids = db_query("SELECT n.nid, n.vid FROM {".$away_table."} cfs INNER JOIN {node} n ON n.nid = cfs.nid WHERE n.type = '".$away_node_type."' AND cfs.".$away_field."_nid = %d AND n.vid = cfs.vid", $home_node->nid);
-  while ($row = db_fetch_object($referenced_nids)) {
-    $collect_referenced_nodes[] = $row;
-  }
-  
-  if (is_array($collect_referenced_nodes)) {
-    foreach ($collect_referenced_nodes as $collect_referenced_node) {
-      corresponding_node_references_remove_node_refs($home_node->nid, $away_field.'_nid', $away_table, $collect_referenced_node->nid);
-      corresponding_node_references_clear_cache($collect_referenced_node);
-    }
-  }
-  
-  if (count($home_node->{$home_field}) > 0) {
-    foreach ($home_node->{$home_field} as $key => $ref_nid) {
-      $referenced_node = node_load($ref_nid['nid']); 
-      if ($referenced_node->nid) {
-        $delta = corresponding_node_references_get_delta($away_table , $referenced_node->vid, $referenced_node->nid);           
-        //check if the ref doesnt allready exists
-        if (!corresponding_node_references_check_ref($away_table, $referenced_node->vid, $referenced_node->nid, $home_node->nid, $away_field.'_nid')) {
-          corresponding_node_references_add_node_ref($away_table, $referenced_node->vid, $referenced_node->nid, $delta + 1, $home_node->nid, $away_field.'_nid'); 
-        }
-        corresponding_node_references_clear_cache($referenced_node);
-      }
-    }
-  }
-}
-
-/**
- * Checks if reference allready exists
- *
- * @param string $table
- * @param int $vid
- * @param int $nid
- * @param int $ref_nid
- * @param string $field
- * @return bool 
- */
-function corresponding_node_references_check_ref($table, $vid, $nid, $ref_nid, $field) {
-  return (db_result(db_query("SELECT nid FROM {".$table."} WHERE nid = %d AND vid = %d AND $field = %d", $nid, $vid, $ref_nid))) ? true : false;  
-}
-
-/**
- * Removes old node refs
- */ 
-function corresponding_node_references_remove_node_refs($ref_nid, $field, $table, $nid) {
-  db_query("DELETE FROM {".$table."} WHERE $field = %d AND nid = %d", $ref_nid, $nid);
-}
-
-/**
- * Removes old node refs after node deletion
- */ 
-function corresponding_node_references_remove_node_refs_after_delete($nid, $field, $table) {
-  db_query("DELETE FROM {".$table."} WHERE $field = %d", $nid);
-}
-
-/**
- * Adds a node ref
- */ 
-function corresponding_node_references_add_node_ref($table, $vid, $nid, $delta, $ref_nid, $field) {
-  db_query("DELETE FROM {".$table."} WHERE $field IS NULL AND nid = %d AND vid = %d", $nid, $vid);
-  db_query("INSERT INTO {".$table."} (vid, nid, delta, $field) VALUES (%d, %d, %d, %d)", $vid, $nid, $delta, $ref_nid);
-}
-
-/**
- * Gets the delta for the new node ref
- */ 
-function corresponding_node_references_get_delta($table, $vid) {
-  return db_result(db_query("SELECT delta FROM {".$table."} WHERE vid = %d ORDER by delta DESC LIMIT 1", $vid));
-}
-
-/**
- * Clears cache for a specific node
- */ 
-function corresponding_node_references_clear_cache($node) {
-  db_query("DELETE FROM {cache_content} WHERE cid = '%s'", 'content:'.$node->nid.':'.$node->vid);
-}
 
 /**
 * Implementation of hook_form_alter()
@@ -320,4 +215,4 @@ function corresponding_node_references_form_alter(&$form, $form_state) {
       }
     }
   }
-} 
\ No newline at end of file
+} 
