function crosswalk()
 {
     global $refer_to_heurist_type_map, $refer_to_heurist_map;
     if (!$this->_have_supplementary_fields) {
         heurist_refer_add_supplementary_fields($this);
     }
     $refer_type = strtolower($this->_type);
     if (!@$refer_to_heurist_type_map[$refer_type]) {
         return NULL;
         // FIXME: probably store an error message somewhere
     }
     $heurist_rectypes = $refer_to_heurist_type_map[$refer_type];
     $base_entry = $last_entry = NULL;
     foreach ($heurist_rectypes as $rt) {
         // construct an empty entry [and its containers]
         unset($new_entry);
         $new_entry =& new HeuristNativeEntry($rt);
         if (!$base_entry) {
             $base_entry =& $new_entry;
         }
         if ($last_entry) {
             $last_entry->setContainerEntry($new_entry);
         }
         $last_entry =& $new_entry;
     }
     $refer_to_heurist_bdts = $refer_to_heurist_map[$refer_type];
     // Finally: actually add values to the native Heurist entry -- convert the refer values one by one
     foreach (array_keys($this->_fields) as $i) {
         unset($refer_field);
         $refer_field =& $this->_fields[$i];
         $heurist_tags = @$refer_to_heurist_bdts[$refer_field->getTagName()];
         if ($heurist_tags) {
             // There is a Heurist type for this refer tag
             if (!is_array($heurist_tags)) {
                 $heurist_tags = array($heurist_tags);
             }
             foreach ($heurist_tags as $heurist_tag) {
                 unset($entry);
                 $entry =& $base_entry;
                 while ($heurist_tag[0] == ':') {
                     // &*(&*(#$&*(%   RIDDLE ME THIS .. why does it not work if I use ->getContainerEntry() ?
                     unset($tmp_entry);
                     $tmp_entry =& $entry->_container;
                     unset($entry);
                     $entry =& $tmp_entry;
                     $heurist_tag = substr($heurist_tag, 1);
                 }
                 if (!$entry) {
                     continue;
                 }
                 // FIXME: need to put in a fuzzy matching lovey-dovey thing here to recognise ANY enum type, not just THESIS TYPE
                 if ($heurist_tag == '243') {
                     //MAGIC NUMBER
                     $entry->addField(new HeuristNativeField($heurist_tag, $refer_field->getRawValue(), decode_thesis_type($refer_field)));
                 } else {
                     if (is_enum_field($heurist_tag)) {
                         $entry->addField(new HeuristNativeField($heurist_tag, $refer_field->getRawValue(), decode_enum($heurist_tag, $refer_field)));
                     } else {
                         if ($heurist_tag == '160') {
                             //MAGIC NUMBER// title field -- cook it a little
                             $entry->addField(new HeuristNativeField($heurist_tag, preg_replace('/\\s*[&]\\s*/', ' and ', $refer_field->getValue())));
                         } else {
                             $entry->addField(new HeuristNativeField($heurist_tag, $refer_field->getValue()));
                         }
                     }
                 }
             }
         } else {
             if ($refer_field->getTagName() == 'K') {
                 // tags are handled specially, of course
                 $base_entry->addTag($refer_field->getRawValue());
             } else {
                 if (@$personal_notes_tags[$refer_field->getTagName()]) {
                     $base_entry->addBkmkNotes($personal_notes_tags[$refer_field->getTagName()] . ': ' . $refer_field->getValue());
                 } else {
                     // No Heurist type for this refer tag, so add it with type 0 to the base-level entry
                     if ($refer_field->_superseded) {
                         continue;
                     }
                     // ... but skip it if it's in another field
                     $base_entry->addField(new HeuristNativeField(0, '%' . $refer_field->getTagName() . ' ' . $refer_field->getValue()));
                 }
             }
         }
     }
     $base_entry->_foreign =& $this;
     return $base_entry;
 }
 function crosswalk()
 {
     global $zotero_to_heurist_detail_map, $zotero_to_heurist_type_map;
     $fields = $this->_raw;
     if (array_key_exists($fields['itemType'], $zotero_to_heurist_type_map)) {
         unset($fields['itemType']);
     }
     // ignore these fields  SAW FIXME  we should have a way to include ignoring input fields in the map or just put all unused field in scratch pad
     unset($fields['dateModified']);
     unset($fields['accessDate']);
     unset($fields['firstCreator']);
     if (array_key_exists($this->_type, $zotero_to_heurist_detail_map)) {
         $type_map = $zotero_to_heurist_detail_map[$this->_type];
     } else {
         $type_map = $zotero_to_heurist_detail_map[''];
     }
     // cook the pages and page fields   FIXME  assumes format "pages sp - ep" consecutive page numbering preceded by the word pages
     if (@$fields['pages'] && !@$fields['start-page'] && array_key_exists('start-page', $type_map)) {
         if (preg_match('/[pages|pp\\.]*\\s*(\\d+)\\s*-\\s*(\\d+)/i', $fields['pages'], $matches)) {
             $fields['start-page'] = $matches[1];
             $fields['end-page'] = $matches[2];
             if ($matches[0] == trim($fields['pages'])) {
                 unset($fields['pages']);
             }
         }
     } else {
         if (@$fields['page'] && !@$fields['start-page'] && array_key_exists('start-page', $type_map)) {
             if (preg_match('/(\\d+)\\s*-\\s*(\\d+)/', $fields['page'], $matches)) {
                 $fields['start-page'] = $matches[1];
                 $fields['end-page'] = $matches[2];
                 if ($matches[0] == trim($fields['page'])) {
                     unset($fields['page']);
                 }
             }
         }
     }
     //cook the date so we have a year value
     if (@$fields['date']) {
         if (preg_match('/^([^-]+?)-00-00\\s+(.+)/', $fields['date'], $matches)) {
             // typically a YEAR
             if (!@$fields['year']) {
                 $fields['year'] = $matches[1];
             }
             $fields['date'] = $matches[2];
         } else {
             if (preg_match('/^(\\S+)\\s.*/', $fields['date'], $matches)) {
                 if (!@$fields['year']) {
                     $fields['year'] = intval($matches[1]);
                 }
                 //FIXME  matches is a date and intval returns the year which seems to be undocumented behavior
                 $fields['date'] = $matches[1];
             }
         }
     }
     // create the Heurist containment heirarchy for this Zotero biblio type
     $last_entry = NULL;
     $new_entry = NULL;
     foreach ($zotero_to_heurist_type_map[$this->_type] as $rt) {
         $entry = new HeuristNativeEntry($rt);
         if ($new_entry == NULL) {
             $new_entry =& $entry;
         } else {
             $last_entry->setContainerEntry($entry);
         }
         $last_entry =& $entry;
     }
     // go through the detail types map and if there is a field value then use the map to
     // attach the value to the correct entry in the containment heirarchy
     foreach ($type_map as $zoteroType => $heuristTag) {
         if (!@$fields[$zoteroType]) {
             continue;
         }
         if (strpos($heuristTag, ':') === FALSE) {
             // straightforward, set field directly
             $entry =& $new_entry;
         } else {
             if ($heuristTag[0] == ':') {
                 unset($entry);
                 $entry =& $new_entry;
                 while ($heuristTag[0] == ':') {
                     unset($tmpEntry);
                     $tmpEntry =& $entry->_container;
                     // why doesn't it use getContainerEntry references?
                     unset($entry);
                     $entry =& $tmpEntry;
                     $heuristTag = substr($heuristTag, 1);
                 }
             } else {
                 //this is a case where we have a reference pointer to a record and we want to add a field to teh record.  FIXME never gets set ?depricate?
                 preg_match('/(\\d+):(\\d+)/', $heuristTag, $matches);
                 $entry =& $new_entry->_references[$matches[1]];
                 $heuristTag = $matches[2];
             }
         }
         if (!is_array($fields[$zoteroType])) {
             if ($heuristTag == '243') {
                 //MAGIC NUMBER//thesis type
                 $entry->addField(new HeuristNativeField($heuristTag, $fields[$zoteroType], decode_thesis_type($fields[$zoteroType])));
             } else {
                 if (is_enum_field($heuristTag)) {
                     $entry->addField(new HeuristNativeField($heuristTag, $fields[$zoteroType], decode_enum($heuristTag, $fields[$zoteroType])));
                 } else {
                     if ($heuristTag == '160') {
                         //MAGIC NUMBER	// title field, cook it a little
                         $val = preg_replace('/\\s*[&]\\s*/', ' and ', $fields[$zoteroType]);
                         $val = preg_replace('/(.+),\\s*(The|A|An)$/', "\$2 \$1", $val);
                         // what is this, a damn library catalogue?
                         $entry->addField(new HeuristNativeField($heuristTag, $val));
                     } else {
                         $entry->addField(new HeuristNativeField($heuristTag, $fields[$zoteroType]));
                     }
                 }
             }
         } else {
             if ($zoteroType == 'tag') {
                 foreach ($fields[$zoteroType] as $f) {
                     $entry->addTag($f);
                 }
             } else {
                 foreach ($fields[$zoteroType] as $f) {
                     $entry->addField(new HeuristNativeField($heuristTag, $f));
                 }
             }
         }
         unset($fields[$zoteroType]);
     }
     // we unset the zotero fields as they are crosswalked; anything that's left should get sent to the scratch field of the base-level entry
     foreach ($fields as $zoteroType => $value) {
         $new_entry->addField(new HeuristNativeField(0, $zoteroType . ' ' . $value));
     }
     $new_entry->_foreign =& $this;
     return $new_entry;
 }