From 37e75387f5dd41deca0bcb49a6e57a7429b36924 Mon Sep 17 00:00:00 2001 From: Chris MacDonald <31731869+chrismacdonaldw@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:26:45 -0300 Subject: [PATCH 01/13] Add new fields to FOXML migration --- .../migrations/dgis_nodes.yml | 481 +++++++++++++++++- 1 file changed, 480 insertions(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index eb204d12..52fc1f77 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -334,7 +334,7 @@ process: property: nodeValue field_description: - << : *base_mods_node - query: 'mods:abstract' + query: 'mods:abstract[@displayLabel="summary"]' - plugin: callback callable: iterator_to_array - plugin: multiple_values @@ -1693,6 +1693,36 @@ process: - plugin: callback callable: array_filter - plugin: null_coalesce + field_related_item_identifier: + - <<: *nested_mods_node + query: 'mods:relatedItem/mods:identifier' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_related_item_genre: + - <<: *nested_mods_node + query: 'mods:relatedItem/mods:genre' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: genre + <<: *generic_term_after + - <<: *generic_term_extract _resource_type: - << : *base_mods_node query: 'mods:typeOfResource' @@ -1973,6 +2003,455 @@ process: default_value: language <<: *generic_term_after - <<: *generic_term_extract + field_degree_name: + - <<: *base_mods_node + query: 'mods:extension/etd:degree/etd:name' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: degree_names + <<: *generic_term_after + - <<: *generic_term_extract + _degree_level: + - <<: *base_mods_node + query: 'mods:extension/etd:degree/etd:level' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + field_degree_level: + - plugin: default_value + source: '@_degree_level' + default_value: Unspecified + - plugin: entity_generate + bundle: degree_levels + bundle_key: vid + entity_type: taxonomy_term + value_key: name + ignore_case: *case_insensitive + field_department: + - <<: *base_mods_node + query: 'mods:extension/etd:degree/etd:discipline' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: discipline + <<: *generic_term_after + - <<: *generic_term_extract + field_institution: + - <<: *base_mods_node + query: 'mods:extension/etd:degree/etd:grantor' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: institution + <<: *generic_term_after + - <<: *generic_term_extract + field_version_identifier: + - <<: *base_mods_node + query: 'mods:note[@type="version identification"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_abstract: + - <<: *base_mods_node + query: 'mods:abstract[@displayLabel="academic"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_open_url: + - <<: *base_mods_node + query: 'mods:identifier[@type="openurl"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_ismn: + - <<: *base_mods_node + query: 'mods:identifier[@type="ismn"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_repec: + - <<: *base_mods_node + query: 'mods:identifier[@type="repec"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_gpo_number: + - <<: *base_mods_node + query: 'mods:identifier[@type="gpo"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_pubmed_central_number: + - <<: *base_mods_node + query: 'mods:identifier[@type="pmcid"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_pubmed_number: + - <<: *base_mods_node + query: 'mods:identifier[@type="pmid"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_ddc_classification: + - <<: *base_mods_node + query: 'mods:classification[@authority="ddc"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_sudoc_number: + - <<: *base_mods_node + query: 'mods:classification[@authority="sudoc"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_swank_classification: + - <<: *base_mods_node + query: 'mods:classification[@authority="swank"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_conference: + - <<: *base_mods_node + query: 'mods:name[@type="conference"]/mods:namePart' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: conference_events + <<: *generic_term_after + - <<: *generic_term_extract + field_series_paragraph: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="series"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_paragraph_generate + validate: *validate + type: series + process_values: true + values: + field_series_titles: + - <<: *nested_mods_node + query: 'mods:titleInfo/mods:title' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: series_titles + <<: *generic_term_after + - <<: *generic_term_extract + field_series_number: + - <<: *nested_mods_node + query: 'mods:titleInfo/mods:partNumber' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_title: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:titleInfo/mods:title' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: titles + <<: *generic_term_after + - <<: *generic_term_extract + field_publication_number: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:titleInfo/mods:partNumber' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_volume_title: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:titleInfo/mods:partName' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_chapter_number: + - <<: *base_mods_node + query: 'mods:part[@type="chapter"]/mods:detail/mods:number' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_section: + - <<: *base_mods_node + query: 'mods:part[@type="section"]/mods:detail/mods:title' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_identifier: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:identifier' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_url: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:location/mods:url' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_genre: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:genre' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: genre + <<: *generic_term_after + - <<: *generic_term_extract + field_extent_total_pages: + - <<: *base_mods_node + query: 'mods:part/mods:extent/mods:total' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_extent_first_page: + - <<: *base_mods_node + query: 'mods:part/mods:extent/mods:start' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_extent_last_page: + - <<: *base_mods_node + query: 'mods:part/mods:extent/mods:end' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_admin_note: + - <<: *base_mods_node + query: 'mods:note[@type="admin"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_funder: + - <<: *base_mods_node + query: 'mods:role/mods:roleTerm="funder"' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: funders + <<: *generic_term_after + - <<: *generic_term_extract + field_sponsorship_information: + - <<: *base_mods_node + query: 'mods:note[@type="funding"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + _use_license: + - <<: *base_mods_node + query: 'mods:accessCondition[@type="use and reproduction"][@displayLabe="Creative Commons"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + field_use_license: + - plugin: default_value + source: '@_use_license' + default_value: Unspecified + - plugin: entity_generate + bundle: creative_commons_licenses_4_0 + bundle_key: vid + entity_type: taxonomy_term + value_key: name + ignore_case: *case_insensitive nid: - plugin: migration_lookup source: '@field_pid' From 1571a041ead1c8cd54eb58453b7ed45dbf77dfcc Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 26 Jul 2024 11:51:18 -0300 Subject: [PATCH 02/13] Related item things are operating inside of the element context already. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 52fc1f77..b384afb2 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1695,7 +1695,7 @@ process: - plugin: null_coalesce field_related_item_identifier: - <<: *nested_mods_node - query: 'mods:relatedItem/mods:identifier' + query: 'mods:identifier' - plugin: callback callable: iterator_to_array - plugin: multiple_values @@ -1709,7 +1709,7 @@ process: - plugin: null_coalesce field_related_item_genre: - <<: *nested_mods_node - query: 'mods:relatedItem/mods:genre' + query: 'mods:genre' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty From 0ffff687492e613fc6e23957012cba66eb32cfa8 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 26 Jul 2024 13:45:12 -0300 Subject: [PATCH 03/13] Fix some inline code docs. Also, change in the invocation recommended by Extended Analysis. --- src/Plugin/migrate/process/Xml/ContextQuery.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Plugin/migrate/process/Xml/ContextQuery.php b/src/Plugin/migrate/process/Xml/ContextQuery.php index 4d825cfa..fa78efd7 100644 --- a/src/Plugin/migrate/process/Xml/ContextQuery.php +++ b/src/Plugin/migrate/process/Xml/ContextQuery.php @@ -27,11 +27,11 @@ class ContextQuery extends ProcessPluginBase { use MissingBehaviorTrait; /** - * The instance on which to run the query. + * Reference to the instance in the row on which to run the query. * - * @var \DOMXPath + * @var string */ - protected mixed $xpath; + protected string $xpath; /** * The query to execute. @@ -84,7 +84,7 @@ public function transform($value, MigrateExecutableInterface $migrate_executable ])); } - return call_user_func([$xpath, $this->method], $this->query, $value); + return $xpath->{$this->method}($this->query, $value); } } From c813fd17d4e79b6a73116fd9d79fc79eb45c21fa Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 26 Jul 2024 13:46:10 -0300 Subject: [PATCH 04/13] Allow the passthrough of the `_mods_xpath` instance. --- .../migrations/dgis_nodes.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index b384afb2..86f0fb18 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1638,6 +1638,10 @@ process: type: related_item process_values: true values: + _mods_xpath: + # XXX: Copy here so it's available for further subprocessing. + - plugin: get + source: parent_row/dest/_mods_xpath field_relationship_type: - << : *nested_mods_node query: '@type' @@ -2209,6 +2213,10 @@ process: type: series process_values: true values: + _mods_xpath: + # XXX: Copy here so it's available for further subprocessing. + - plugin: get + source: parent_row/dest/_mods_xpath field_series_titles: - <<: *nested_mods_node query: 'mods:titleInfo/mods:title' @@ -2405,7 +2413,7 @@ process: - plugin: null_coalesce field_funder: - <<: *base_mods_node - query: 'mods:role/mods:roleTerm="funder"' + query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"]/mods:namePart' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty From 4934fe2a57b3b040fc1d0d993a984a12e0dd1cd7 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 26 Jul 2024 15:39:41 -0300 Subject: [PATCH 05/13] Format chain of exceptions to facilitate debugging. Also, prevent whatever was causing the serialization issue? Was apparently related to the "sub process" plugin naively rethrowing exceptions as `\Exception`, which would've proceeded with an undefined `$save` variable? --- src/MigrateBatchExecutable.php | 39 +++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/MigrateBatchExecutable.php b/src/MigrateBatchExecutable.php index 9344dc6d..eb23c5b5 100644 --- a/src/MigrateBatchExecutable.php +++ b/src/MigrateBatchExecutable.php @@ -237,6 +237,30 @@ protected function enqueue() { return MigrationInterface::RESULT_COMPLETED; } + /** + * Helper to format exceptions. + * + * @param \Exception $e + * The exception to format. + * @param string $prefix + * Prefix to tack onto exceptions, such that causes can be added + * recursively. + * @param int $depth + * Recursive depth, to augment message. + * + * @return string + * The formatted exception. + */ + protected function formatException(\Throwable $e, string $prefix = 'Initial', int $depth = 0) : string { + $parts = []; + $parts[] = "$prefix message: {$e->getMessage()}"; + $parts[] = "$prefix trace:\n{$e->getTraceAsString()}"; + if ($e->getPrevious()) { + $parts[] = $this->formatException($e->getPrevious(), "--- Cause #{$depth}", $depth + 1); + } + return implode("\n", $parts); + } + /** * The meat of processing a row. * @@ -257,11 +281,6 @@ protected function processRowFromQueue(Row $row) { $this->processRow($row); $save = TRUE; } - catch (MigrateException $e) { - $this->getIdMap()->saveIdMapping($row, [], $e->getStatus()); - $this->saveMessage($e->getMessage(), $e->getLevel()); - $save = FALSE; - } catch (MigrateSkipRowException $e) { if ($e->getSaveToMap()) { $id_map->saveIdMapping($row, [], MigrateIdMapInterface::STATUS_IGNORED); @@ -271,6 +290,16 @@ protected function processRowFromQueue(Row $row) { } $save = FALSE; } + catch (MigrateException $e) { + $this->getIdMap()->saveIdMapping($row, [], $e->getStatus()); + $this->saveMessage($this->formatException($e), $e->getLevel()); + $save = FALSE; + } + catch (\Exception $e) { + $this->getIdMap()->saveIdMapping($row, [], MigrateIdMapInterface::STATUS_FAILED); + $this->saveMessage($this->formatException($e), MigrationInterface::MESSAGE_ERROR); + $save = FALSE; + } if ($save) { try { From 0adcd858853c71a19cfbee2bb96d4d442f4c0899 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 10:56:36 -0300 Subject: [PATCH 06/13] Pull subject apart, and something theoretical for "funders". --- .../migrations/dgis_nodes.yml | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 86f0fb18..466817b4 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1779,7 +1779,7 @@ process: - plugin: multiple_values - plugin: dgi_migrate.subproperty property: nodeValue - _subject_topic: + field_subject: - << : *base_mods_node query: 'mods:subject/mods:topic[normalize-space()]' - plugin: callback @@ -1795,7 +1795,7 @@ process: default_value: subject <<: *generic_term_after - <<: *generic_term_extract - _subject_name_personal: + field_subject_name_person: - << : *base_mods_node query: 'mods:subject/mods:name[@type="personal" or not(@type)][normalize-space()]' - plugin: callback @@ -1866,7 +1866,7 @@ process: method: row - plugin: dgi_migrate.process.single_extract index: [ target_id ] - _subject_name_corporate: + field_subject_name_organization: - << : *base_mods_node query: 'mods:subject/mods:name[@type="corporate"][normalize-space()]' - plugin: callback @@ -1927,13 +1927,6 @@ process: method: row - plugin: dgi_migrate.process.single_extract index: [ target_id ] - field_subject: - - plugin: get - source: - - '@_subject_topic' - - '@_subject_name_personal' - - '@_subject_name_corporate' - - plugin: flatten field_sub_location: - << : *base_mods_node query: 'mods:location/mods:holdingSimple/mods:copyInformation/mods:subLocation' @@ -2413,7 +2406,7 @@ process: - plugin: null_coalesce field_funder: - <<: *base_mods_node - query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"]/mods:namePart' + query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"][normalize-space(mods:namePart)]' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty @@ -2425,7 +2418,31 @@ process: _vid: - plugin: default_value default_value: funders - <<: *generic_term_after + _auth_value_uri: + - <<: *nested_mods_node + query: 'string(@valueURI)' + method: evaluate + _auth_source: + - <<: *nested_mods_node + query: 'string(@authority)' + method: evaluate + _value: + - <<: *nested_mods_node + query: 'normalize-space(mods:namePart)' + method: evaluate + actual: + - plugin: get + source: + - '@_auth_source' + - '@_auth_value_uri' + - '@_value' + # XXX: Needs to be provided wherever this is used, corresponding + # to the vocab in which to do the things. + - '@_vid' + - plugin: flatten + - plugin: migration_lookup + migration: dgis_stub_terms_generic + stub_id: dgis_stub_terms_generic - <<: *generic_term_extract field_sponsorship_information: - <<: *base_mods_node From 8a09a33fd1fe45a3a7f33a4180997ecf6f8f8a20 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 11:18:05 -0300 Subject: [PATCH 07/13] Update `field_funders`. --- .../migrations/dgis_nodes.yml | 67 ++++++++++++------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 466817b4..b6b28e03 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -2405,7 +2405,7 @@ process: callable: array_filter - plugin: null_coalesce field_funder: - - <<: *base_mods_node + - << : *base_mods_node query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"][normalize-space(mods:namePart)]' - plugin: callback callable: iterator_to_array @@ -2415,35 +2415,56 @@ process: - plugin: dgi_migrate.sub_process process_values: true values: - _vid: - - plugin: default_value - default_value: funders - _auth_value_uri: - - <<: *nested_mods_node - query: 'string(@valueURI)' + _authority: + - << : *nested_mods_node + query: 'normalize-space(@authority)' method: evaluate - _auth_source: - - <<: *nested_mods_node - query: 'string(@authority)' + _value_uri: + - << : *nested_mods_node + query: 'normalize-space(@valueURI)' method: evaluate - _value: - - <<: *nested_mods_node - query: 'normalize-space(mods:namePart)' + _date_name: + - << : *nested_mods_node + query: 'normalize-space(mods:namePart[@type="date"][normalize-space()][1])' method: evaluate - actual: + _display_form: + - << : *nested_mods_node + query: 'normalize-space(mods:displayForm[normalize-space()][1])' + method: evaluate + _untyped_names: + - << : *nested_mods_node + query: 'normalize-space(mods:namePart[not(@type)][normalize-space()])' + method: evaluate + _affiliation_lookup: + - << : *nested_mods_node + query: 'normalize-space(mods:affiliation[normalize-space()])' + method: evaluate + - plugin: skip_on_empty + method: process + - plugin: migration_lookup + migration: dgis_stub_terms_affiliate + stub_id: dgis_stub_terms_affiliate + _affiliation: + - plugin: default_value + source: '@_affiliation_lookup' + default_value: '' + target_id: - plugin: get source: - - '@_auth_source' - - '@_auth_value_uri' - - '@_value' - # XXX: Needs to be provided wherever this is used, corresponding - # to the vocab in which to do the things. - - '@_vid' + - '@_authority' + - '@_value_uri' + - '@_untyped_names' + - '@_date_name' + - '@_display_form' + - '@_affiliation' - plugin: flatten - plugin: migration_lookup - migration: dgis_stub_terms_generic - stub_id: dgis_stub_terms_generic - - <<: *generic_term_extract + migration: dgis_stub_terms_corporate_body + stub_id: dgis_stub_terms_corporate_body + - plugin: skip_on_empty + method: row + - plugin: dgi_migrate.process.single_extract + index: [ target_id ] field_sponsorship_information: - <<: *base_mods_node query: 'mods:note[@type="funding"]' From b8e254941a6f9be86c2921f5a7b08a8e36804f5c Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 11:25:37 -0300 Subject: [PATCH 08/13] Fix typo in `displayLabel` attribute XPath. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index b6b28e03..c102c83f 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -2479,7 +2479,7 @@ process: - plugin: null_coalesce _use_license: - <<: *base_mods_node - query: 'mods:accessCondition[@type="use and reproduction"][@displayLabe="Creative Commons"]' + query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons"]' - plugin: callback callable: iterator_to_array - plugin: multiple_values From 41a9893c696e01c1b3ce18d239b8e2852d876350 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 12:15:39 -0300 Subject: [PATCH 09/13] Mask undesired note types. They're handled in their own dedicated fields. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index c102c83f..a856696b 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -677,7 +677,7 @@ process: - plugin: null_coalesce field_note_paragraph: - << : *base_mods_node - query: 'mods:note' + query: 'mods:note[not(@type="funding" or @type="admin")]' - plugin: callback callable: iterator_to_array - plugin: multiple_values From 598710fe815c07a60aa36824865154178ee79f71 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 12:44:54 -0300 Subject: [PATCH 10/13] Avoid null_coalescing repeatable things. --- .../migrations/dgis_nodes.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index a856696b..8ba48b08 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -635,7 +635,6 @@ process: - plugin: dgi_migrate.subproperty property: nodeValue - plugin: single_value - - plugin: null_coalesce field_item_identifier: - << : *base_mods_node query: 'mods:location/mods:holdingSimple/mods:copyInformation/mods:itemIdentifier' @@ -655,7 +654,6 @@ process: - plugin: dgi_migrate.subproperty property: nodeValue - plugin: single_value - - plugin: null_coalesce field_local_identifier: - << : *base_mods_node query: 'mods:identifier[@type="local"]' @@ -719,7 +717,6 @@ process: - plugin: dgi_migrate.subproperty property: nodeValue - plugin: single_value - - plugin: null_coalesce field_linked_agent: - << : *base_mods_node query: 'mods:name[@type="personal"]' @@ -2403,7 +2400,6 @@ process: - plugin: single_value - plugin: callback callable: array_filter - - plugin: null_coalesce field_funder: - << : *base_mods_node query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"][normalize-space(mods:namePart)]' @@ -2476,7 +2472,6 @@ process: - plugin: single_value - plugin: callback callable: array_filter - - plugin: null_coalesce _use_license: - <<: *base_mods_node query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons"]' From c861e98e472cac3e0efd98af8720892e41427f61 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 14:10:12 -0300 Subject: [PATCH 11/13] Squash uses of `entity_generate`. Entities creates under it (instead of via stub migrations) would not be removed when rolling back. --- .../migrations/dgis_nodes.yml | 207 +++++++++++++----- 1 file changed, 153 insertions(+), 54 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 8ba48b08..e7b40179 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1729,22 +1729,60 @@ process: query: 'mods:typeOfResource' - plugin: callback callable: iterator_to_array + - plugin: skip_on_empty + method: process - plugin: multiple_values - - plugin: dgi_migrate.subproperty - property: nodeValue - - plugin: single_value - - plugin: callback - callable: array_filter - field_resource_type: + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: resource_types + <<: *generic_term_after + - <<: *generic_term_extract + _unspecified_resource_type: - plugin: default_value - source: '@_resource_type' default_value: Unspecified - - plugin: entity_generate - bundle: resource_types - bundle_key: vid - entity_type: taxonomy_term - value_key: name - ignore_case: *case_insensitive + - plugin: gate + use_as_key: '@_resource_type' + valid_keys: + - null + key_direction: lock + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: resource_types + _auth_value_uri: + - plugin: default_value + default_value: '' + _auth_source: + - plugin: default_value + default_value: '' + _value: + - plugin: get + source: parent_value + actual: + - plugin: get + source: + - '@_auth_source' + - '@_auth_value_uri' + - '@_value' + # XXX: Needs to be provided wherever this is used, corresponding + # to the vocab in which to do the things. + - '@_vid' + - plugin: flatten + - plugin: migration_lookup + migration: dgis_stub_terms_generic + stub_id: dgis_stub_terms_generic + - <<: *generic_term_extract + field_resource_type: + - plugin: get + source: + - '@_resource_type' + - '@_unspecified_resource_type' + - plugin: null_coalesce field_restriction_on_access: - << : *base_mods_node query: 'mods:accessCondition[@type="restriction on access"]' @@ -1753,21 +1791,6 @@ process: - plugin: multiple_values - plugin: dgi_migrate.subproperty property: nodeValue - # XXX: Was intended as outbound mapping, not inbound. Let's just comment for now. - #field_rights_statement: - # - << : *base_mods_node - # query: 'mods:accessCondition[@type="use and reproduction"]' - # - plugin: callback - # callable: iterator_to_array - # - plugin: multiple_values - # - plugin: dgi_migrate.subproperty - # property: nodeValue - # - plugin: entity_generate - # bundle: rights_statements - # bundle_key: vid - # entity_type: taxonomy_term - # value_key: name - # ignore_case: *case_insensitive field_shelf_locator: - << : *base_mods_node query: 'mods:location/mods:holdingSimple/mods:copyInformation/mods:shelfLocator' @@ -2018,22 +2041,60 @@ process: query: 'mods:extension/etd:degree/etd:level' - plugin: callback callable: iterator_to_array + - plugin: skip_on_empty + method: process - plugin: multiple_values - - plugin: dgi_migrate.subproperty - property: nodeValue - - plugin: single_value - - plugin: callback - callable: array_filter - field_degree_level: + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: degree_levels + <<: *generic_term_after + - <<: *generic_term_extract + _unspecified_degree_level: - plugin: default_value - source: '@_degree_level' default_value: Unspecified - - plugin: entity_generate - bundle: degree_levels - bundle_key: vid - entity_type: taxonomy_term - value_key: name - ignore_case: *case_insensitive + - plugin: gate + use_as_key: '@_degree_level' + valid_keys: + - null + key_direction: unlock + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: degree_levels + _auth_value_uri: + - plugin: default_value + default_value: '' + _auth_source: + - plugin: default_value + default_value: '' + _value: + - plugin: get + source: parent_value + actual: + - plugin: get + source: + - '@_auth_source' + - '@_auth_value_uri' + - '@_value' + # XXX: Needs to be provided wherever this is used, corresponding + # to the vocab in which to do the things. + - '@_vid' + - plugin: flatten + - plugin: migration_lookup + migration: dgis_stub_terms_generic + stub_id: dgis_stub_terms_generic + - <<: *generic_term_extract + field_degree_level: + - plugin: get + source: + - '@_degree_level' + - '@_unspecified_degree_level' + - plugin: null_coalesce field_department: - <<: *base_mods_node query: 'mods:extension/etd:degree/etd:discipline' @@ -2477,22 +2538,60 @@ process: query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons"]' - plugin: callback callable: iterator_to_array + - plugin: skip_on_empty + method: process - plugin: multiple_values - - plugin: dgi_migrate.subproperty - property: nodeValue - - plugin: single_value - - plugin: callback - callable: array_filter - field_use_license: + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: creative_commons_licenses_4_0 + <<: *generic_term_after + - <<: *generic_term_extract + _unspecified_use_license: - plugin: default_value - source: '@_use_license' default_value: Unspecified - - plugin: entity_generate - bundle: creative_commons_licenses_4_0 - bundle_key: vid - entity_type: taxonomy_term - value_key: name - ignore_case: *case_insensitive + - plugin: gate + use_as_key: '@_resource_type' + valid_keys: + - null + key_direction: lock + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: creative_commons_licenses_4_0 + _auth_value_uri: + - plugin: default_value + default_value: '' + _auth_source: + - plugin: default_value + default_value: '' + _value: + - plugin: get + source: parent_value + actual: + - plugin: get + source: + - '@_auth_source' + - '@_auth_value_uri' + - '@_value' + # XXX: Needs to be provided wherever this is used, corresponding + # to the vocab in which to do the things. + - '@_vid' + - plugin: flatten + - plugin: migration_lookup + migration: dgis_stub_terms_generic + stub_id: dgis_stub_terms_generic + - <<: *generic_term_extract + field_use_license: + - plugin: get + source: + - '@_use_license' + - '@_unspecified_use_license' + - plugin: flatten nid: - plugin: migration_lookup source: '@field_pid' From bd232b04d36b0943c2814d9e668f73f4412a6d7e Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 14:47:37 -0300 Subject: [PATCH 12/13] Delicious copypasta. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index e7b40179..0d9acca5 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -2553,7 +2553,7 @@ process: - plugin: default_value default_value: Unspecified - plugin: gate - use_as_key: '@_resource_type' + use_as_key: '@_use_license' valid_keys: - null key_direction: lock From b4debca54d083cfad094a4689e31226fdc9ce6ea Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 14:52:05 -0300 Subject: [PATCH 13/13] Whatever, allow for the typo. Also, fix up the gate lock business. --- .../migrations/dgis_nodes.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 0d9acca5..e3d6e5cf 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1747,7 +1747,7 @@ process: use_as_key: '@_resource_type' valid_keys: - null - key_direction: lock + key_direction: unlock - plugin: dgi_migrate.sub_process process_values: true values: @@ -2535,7 +2535,7 @@ process: callable: array_filter _use_license: - <<: *base_mods_node - query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons"]' + query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons" or @displayLabe="Creative Commons"]' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty @@ -2556,7 +2556,7 @@ process: use_as_key: '@_use_license' valid_keys: - null - key_direction: lock + key_direction: unlock - plugin: dgi_migrate.sub_process process_values: true values: