/**
 * 
 *
 * @param string $ps_refinery_name
 * @param string $ps_table
 * @param array $pa_parents 
 * @param array $pa_source_data
 * @param array $pa_item
 * @param int $pn_c
 * @param KLogger $o_log
 * 
 * @return int
 */
function caProcessRefineryParents($ps_refinery_name, $ps_table, $pa_parents, $pa_source_data, $pa_item, $pn_c, $pa_options = null)
{
    global $g_ui_locale_id;
    if (!is_array($pa_options)) {
        $pa_options = array();
    }
    $o_log = caGetOption('log', $pa_options, null);
    $o_reader = caGetOption('reader', $pa_options, null);
    $o_trans = caGetOption('transaction', $pa_options, null);
    $vn_list_id = caGetOption('list_id', $pa_options, null);
    $vb_hierarchy_mode = caGetOption('hierarchyMode', $pa_options, false);
    if (!is_array($pa_parents)) {
        $pa_parents = array($pa_parents);
    }
    $vn_id = null;
    $pa_parents = array_reverse($pa_parents);
    foreach ($pa_parents as $vn_i => $va_parent) {
        if (!is_array($va_parent)) {
            $o_log->logWarn(_t('[%2] Parents options invalid. Did you forget to pass a list? Parents list passed was: %1', print_r($pa_parents, true), $ps_refinery_name));
            break;
        }
        $vs_name = BaseRefinery::parsePlaceholder($va_parent['name'], $pa_source_data, $pa_item, $pn_c, array('reader' => $o_reader, 'returnAsString' => true, 'delimiter' => ' '));
        $vs_idno = BaseRefinery::parsePlaceholder($va_parent['idno'], $pa_source_data, $pa_item, $pn_c, array('reader' => $o_reader, 'returnAsString' => true, 'delimiter' => ' '));
        $vs_type = BaseRefinery::parsePlaceholder($va_parent['type'], $pa_source_data, $pa_item, $pn_c, array('reader' => $o_reader, 'returnAsString' => true, 'delimiter' => ' '));
        if (!$vs_name && !$vs_idno) {
            continue;
        }
        if (!$vs_name) {
            continue;
        }
        //$vs_name = $vs_idno; }
        $va_attributes = isset($va_parent['attributes']) && is_array($va_parent['attributes']) ? $va_parent['attributes'] : array();
        foreach ($va_attributes as $vs_element_code => $va_attrs) {
            if (is_array($va_attrs)) {
                foreach ($va_attrs as $vs_k => $vs_v) {
                    // BaseRefinery::parsePlaceholder may return an array if the input format supports repeated values (as XML does)
                    // DataMigrationUtils::getCollectionID(), which ca_data_importers::importDataFromSource() uses to create related collections
                    // only supports non-repeating attribute values, so we join any values here and call it a day.
                    $va_attributes[$vs_element_code][$vs_k] = BaseRefinery::parsePlaceholder($vs_v, $pa_source_data, $pa_item, $pn_c, array('reader' => $o_reader, 'returnAsString' => true, 'delimiter' => ' '));
                }
            } else {
                $va_attributes[$vs_element_code] = array($vs_element_code => BaseRefinery::parsePlaceholder($va_attrs, $pa_source_data, $pa_item, $pn_c, array('reader' => $o_reader, 'returnAsString' => true, 'delimiter' => ' ')));
            }
        }
        $va_attributes['idno'] = $vs_idno;
        $va_attributes['parent_id'] = $vn_id;
        if (isset($va_parent['rules']) && is_array($va_parent['rules'])) {
            foreach ($va_parent['rules'] as $va_rule) {
                $vm_ret = ExpressionParser::evaluate($va_rule['trigger'], $pa_source_data);
                if (!ExpressionParser::hadError() && (bool) $vm_ret) {
                    foreach ($va_rule['actions'] as $va_action) {
                        if (!is_array($va_action) && strtolower($va_action) == 'skip') {
                            $va_action = array('action' => 'skip');
                        }
                        switch ($vs_action_code = strtolower($va_action['action'])) {
                            case 'set':
                                switch ($va_action['target']) {
                                    case 'name':
                                        $vs_name = BaseRefinery::parsePlaceholder($va_action['value'], $pa_source_data, $pa_item, $pn_c, array('reader' => $o_reader, 'returnAsString' => true, 'delimiter' => ' '));
                                        break;
                                    case 'type':
                                        $vs_type = BaseRefinery::parsePlaceholder($va_action['value'], $pa_source_data, $pa_item, $pn_c, array('reader' => $o_reader, 'returnAsString' => true, 'delimiter' => ' '));
                                        break;
                                    default:
                                        $va_attributes[$va_action['target']] = BaseRefinery::parsePlaceholder($va_action['value'], $pa_source_data, $pa_item, $pn_c, array('reader' => $o_reader, 'returnAsString' => true, 'delimiter' => ' '));
                                        break;
                                }
                                break;
                            case 'skip':
                            default:
                                if ($o_log) {
                                    if ($vs_action_code != 'skip') {
                                        $o_log->logInfo(_t('[%3] Parent was skipped using rule "%1" with default action because an invalid action ("%2") was specified', $va_rule['trigger'], $vs_action_code, $ps_refinery_name));
                                    } else {
                                        $o_log->logDebug(_t('[%3] Parent was skipped using rule "%1" with action "%2"', $va_rule['trigger'], $vs_action_code, $ps_refinery_name));
                                    }
                                }
                                continue 4;
                                break;
                        }
                    }
                } elseif (ExpressionParser::hadError() && $o_log) {
                    $o_log->logError(_t('[%3] Error processing rule "%1" as an error occurred. Error number was "%2"', $va_rule['trigger'], ExpressionParser::$s_last_error, $ps_refinery_name));
                }
            }
        }
        $va_match_on = caGetOption("{$ps_refinery_name}_dontMatchOnLabel", $pa_item['settings'], false) ? array('idno') : array('idno', 'label');
        $pa_options = array_merge(array('matchOn' => $va_match_on), $pa_options);
        switch ($ps_table) {
            case 'ca_objects':
                $vn_id = DataMigrationUtils::getObjectID($vs_name, $vn_id, $vs_type, $g_ui_locale_id, $va_attributes, $pa_options);
                $va_attributes['preferred_labels']['name'] = $va_attributes['_preferred_labels'] = $vs_name;
                break;
            case 'ca_entities':
                $vn_id = DataMigrationUtils::getEntityID($va_entity_label = DataMigrationUtils::splitEntityName($vs_name, $pa_options), $vs_type, $g_ui_locale_id, $va_attributes, $pa_options);
                $va_attributes['preferred_labels'] = $va_entity_label;
                $va_attributes['_preferred_labels'] = $vs_name;
                break;
            case 'ca_places':
                if (!$vn_id) {
                    // get place hierarchy root
                    require_once __CA_MODELS_DIR__ . "/ca_places.php";
                    $t_place = new ca_places();
                    if ($o_trans) {
                        $t_place->setTransaction($o_trans);
                    }
                    $vn_id = $pa_options['defaultParentID'];
                    if (!$vn_id) {
                        $vn_id = $t_place->getHierarchyRootID($pa_options['hierarchyID']);
                    }
                    $va_attributes['parent_id'] = $vn_id;
                }
                $vn_id = DataMigrationUtils::getPlaceID($vs_name, $vn_id, $vs_type, $g_ui_locale_id, $va_attributes, $pa_options);
                $va_attributes['preferred_labels']['name'] = $va_attributes['_preferred_labels'] = $vs_name;
                break;
            case 'ca_occurrences':
                $vn_id = DataMigrationUtils::getOccurrenceID($vs_name, $vn_id, $vs_type, $g_ui_locale_id, $va_attributes, $pa_options);
                $va_attributes['preferred_labels']['name'] = $va_attributes['_preferred_labels'] = $vs_name;
                break;
            case 'ca_collections':
                $vn_id = DataMigrationUtils::getCollectionID($vs_name, $vs_type, $g_ui_locale_id, $va_attributes, $pa_options);
                $va_attributes['preferred_labels']['name'] = $va_attributes['_preferred_labels'] = $vs_name;
                break;
            case 'ca_loans':
                $vn_id = DataMigrationUtils::getLoanID($vs_name, $vs_type, $g_ui_locale_id, $va_attributes, $pa_options);
                $va_attributes['preferred_labels']['name'] = $va_attributes['_preferred_labels'] = $vs_name;
                break;
            case 'ca_movements':
                $vn_id = DataMigrationUtils::getMovementID($vs_name, $vs_type, $g_ui_locale_id, $va_attributes, $pa_options);
                $va_attributes['preferred_labels']['name'] = $va_attributes['_preferred_labels'] = $vs_name;
                break;
            case 'ca_list_items':
                if (!$vn_list_id) {
                    if ($o_log) {
                        $o_log->logDebug(_t('[importHelpers:caProcessRefineryParents] List was not specified'));
                    }
                    return null;
                }
                if (!$vn_id) {
                    // get place hierarchy root
                    require_once __CA_MODELS_DIR__ . "/ca_lists.php";
                    $t_list = new ca_lists();
                    if ($o_trans) {
                        $t_list->setTransaction($o_trans);
                    }
                    $vn_id = $t_list->getRootItemIDForList($vn_list_id);
                    $va_attributes['parent_id'] = $vn_id;
                }
                $vn_id = DataMigrationUtils::getListItemID($vn_list_id, $vs_name, $vs_type, $g_ui_locale_id, $va_attributes, $pa_options);
                $va_attributes['preferred_labels']['name_singular'] = $va_attributes['preferred_labels']['name_plural'] = $vs_name;
                break;
            case 'ca_storage_locations':
                if (!$vn_id) {
                    // get storage location hierarchy root
                    require_once __CA_MODELS_DIR__ . "/ca_storage_locations.php";
                    $t_loc = new ca_storage_locations();
                    if ($o_trans) {
                        $t_loc->setTransaction($o_trans);
                    }
                    $vn_id = $t_loc->getHierarchyRootID();
                    $va_attributes['parent_id'] = $vn_id;
                }
                $vn_id = DataMigrationUtils::getStorageLocationID($vs_name, $vn_id, $vs_type, $g_ui_locale_id, $va_attributes, $pa_options);
                $va_attributes['preferred_labels']['name'] = $va_attributes['_preferred_labels'] = $vs_name;
                break;
            default:
                if ($o_log) {
                    $o_log->logDebug(_t('[importHelpers:caProcessRefineryParents] Invalid table %1', $ps_table));
                }
                return null;
                break;
        }
        $va_attributes['locale_id'] = $g_ui_locale_id;
        if ($o_log) {
            $o_log->logDebug(_t('[%6] Got parent %1 (%2) with id %3 and type %4 for %5', $vs_name, $vs_idno, $vn_id, $vs_type, $vs_name, $ps_refinery_name));
        }
    }
    if ($vb_hierarchy_mode) {
        return $va_attributes;
    }
    return $vn_id;
}
                                case 'Coordinates':
                                    break 2;
                            }
                        }
                    }
                    break;
                    # ---------------------------
            }
        }
        $o_xml->close();
    }
}
$t_place = new ca_places();
$t_parent = new ca_places();
$t_place->setMode(ACCESS_WRITE);
$vn_tgn_root_id = $t_parent->getHierarchyRootID($vn_tgn_id);
if (true) {
    print "[Notice] LINKING TERMS IN HIERARCHY...\n";
    $vn_last_message_length = 0;
    $va_place_id_cache = array();
    for ($vn_file_index = 1; $vn_file_index <= 15; $vn_file_index++) {
        $o_xml->open("tgn_xml_12/TGN{$vn_file_index}.xml");
        print "[Notice] READING TERMS FROM TGN{$vn_file_index}.xml...\n";
        $va_subject = array();
        while ($o_xml->read()) {
            switch ($o_xml->name) {
                # ---------------------------
                case 'Subject':
                    if ($o_xml->nodeType == XMLReader::END_ELEMENT) {
                        $vs_child_id = $va_subject['subject_id'];
                        $vs_parent_id = $va_subject['preferred_parent_subject_id'];