datacite-mapping 0.1.17.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (205) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +33 -0
  3. data/README.md +93 -150
  4. data/datacite-mapping.gemspec +1 -1
  5. data/lib/datacite/mapping.rb +12 -27
  6. data/lib/datacite/mapping/alternate_identifier.rb +2 -0
  7. data/lib/datacite/mapping/contributor.rb +6 -2
  8. data/lib/datacite/mapping/creator.rb +33 -3
  9. data/lib/datacite/mapping/date.rb +28 -76
  10. data/lib/datacite/mapping/date_value.rb +116 -0
  11. data/lib/datacite/mapping/description.rb +9 -8
  12. data/lib/datacite/mapping/funding_reference.rb +20 -5
  13. data/lib/datacite/mapping/geo_location.rb +25 -4
  14. data/lib/datacite/mapping/geo_location_box.rb +10 -8
  15. data/lib/datacite/mapping/geo_location_node.rb +68 -0
  16. data/lib/datacite/mapping/geo_location_point.rb +8 -8
  17. data/lib/datacite/mapping/geo_location_polygon.rb +76 -0
  18. data/lib/datacite/mapping/identifier.rb +23 -11
  19. data/lib/datacite/mapping/module_info.rb +3 -3
  20. data/lib/datacite/mapping/name_identifier.rb +1 -0
  21. data/lib/datacite/mapping/namespace_extensions.rb +12 -0
  22. data/lib/datacite/mapping/read_only_nodes.rb +65 -0
  23. data/lib/datacite/mapping/related_identifier.rb +28 -0
  24. data/lib/datacite/mapping/resource.rb +88 -43
  25. data/lib/datacite/mapping/rights.rb +2 -0
  26. data/lib/datacite/mapping/subject.rb +10 -9
  27. data/lib/datacite/mapping/title.rb +7 -11
  28. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3059p-mrt-datacite.xml +0 -0
  29. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r31017-mrt-datacite.xml +0 -0
  30. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3201j-mrt-datacite.xml +0 -0
  31. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r33w26-mrt-datacite.xml +0 -0
  32. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r34s3v-mrt-datacite.xml +0 -0
  33. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r36p4t-mrt-datacite.xml +0 -0
  34. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r39g6f-mrt-datacite.xml +0 -0
  35. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3cc7d-mrt-datacite.xml +0 -0
  36. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3d59d-mrt-datacite.xml +0 -0
  37. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3f59q-mrt-datacite.xml +0 -0
  38. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3g591-mrt-datacite.xml +0 -0
  39. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3k016-mrt-datacite.xml +0 -0
  40. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3kw2j-mrt-datacite.xml +0 -0
  41. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3mw2v-mrt-datacite.xml +0 -0
  42. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3np4v-mrt-datacite.xml +0 -0
  43. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3pp45-mrt-datacite.xml +0 -0
  44. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3rp4s-mrt-datacite.xml +0 -0
  45. data/spec/data/{dash1-datacite-xml → dash1}/dataone-ark+=c5146=r3tg63-mrt-datacite.xml +0 -0
  46. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d1159q-mrt-datacite.xml +0 -0
  47. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d17g6j-mrt-datacite.xml +0 -0
  48. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d1c88g-mrt-datacite.xml +0 -0
  49. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d1cc74-mrt-datacite.xml +0 -0
  50. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d1h019-mrt-datacite.xml +0 -0
  51. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d1ms3x-mrt-datacite.xml +0 -0
  52. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d1mw2k-mrt-datacite.xml +0 -0
  53. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d1rg66-mrt-datacite.xml +0 -0
  54. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d1rp4h-mrt-datacite.xml +0 -0
  55. data/spec/data/{dash1-datacite-xml → dash1}/ucb-ark+=b6078=d1wc7s-mrt-datacite.xml +0 -0
  56. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1001p-mrt-datacite.xml +0 -0
  57. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1059f-mrt-datacite.xml +0 -0
  58. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d11010-mrt-datacite.xml +0 -0
  59. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1159r-mrt-datacite.xml +0 -0
  60. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d12019-mrt-datacite.xml +0 -0
  61. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d12s30-mrt-datacite.xml +0 -0
  62. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1301m-mrt-datacite.xml +0 -0
  63. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d13s39-mrt-datacite.xml +0 -0
  64. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d13w2z-mrt-datacite.xml +0 -0
  65. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d14s3m-mrt-datacite.xml +0 -0
  66. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d15k5m-mrt-datacite.xml +0 -0
  67. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d15p48-mrt-datacite.xml +0 -0
  68. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d16k5x-mrt-datacite.xml +0 -0
  69. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d16p4k-mrt-datacite.xml +0 -0
  70. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d17g6k-mrt-datacite.xml +0 -0
  71. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d17p4w-mrt-datacite.xml +0 -0
  72. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d18g6w-mrt-datacite.xml +0 -0
  73. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1988w-mrt-datacite.xml +0 -0
  74. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d19g66-mrt-datacite.xml +0 -0
  75. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1b886-mrt-datacite.xml +0 -0
  76. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1bc7v-mrt-datacite.xml +0 -0
  77. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1c88h-mrt-datacite.xml +0 -0
  78. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1cc75-mrt-datacite.xml +0 -0
  79. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1d595-mrt-datacite.xml +0 -0
  80. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1f30c-mrt-datacite.xml +0 -0
  81. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1f59g-mrt-datacite.xml +0 -0
  82. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1g011-mrt-datacite.xml +0 -0
  83. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1g59s-mrt-datacite.xml +0 -0
  84. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1h01b-mrt-datacite.xml +0 -0
  85. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1h593-mrt-datacite.xml +0 -0
  86. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1j01n-mrt-datacite.xml +0 -0
  87. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1js3b-mrt-datacite.xml +0 -0
  88. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1k01z-mrt-datacite.xml +0 -0
  89. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1ks3n-mrt-datacite.xml +0 -0
  90. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1kw29-mrt-datacite.xml +0 -0
  91. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1ms3z-mrt-datacite.xml +0 -0
  92. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1mw2m-mrt-datacite.xml +0 -0
  93. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1np4m-mrt-datacite.xml +0 -0
  94. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1pk58-mrt-datacite.xml +0 -0
  95. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1pp4x-mrt-datacite.xml +0 -0
  96. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1qg6x-mrt-datacite.xml +0 -0
  97. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1qp47-mrt-datacite.xml +0 -0
  98. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1rg67-mrt-datacite.xml +0 -0
  99. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1rp4j-mrt-datacite.xml +0 -0
  100. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1sg6j-mrt-datacite.xml +0 -0
  101. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1t88j-mrt-datacite.xml +0 -0
  102. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1tg6v-mrt-datacite.xml +0 -0
  103. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1v88v-mrt-datacite.xml +0 -0
  104. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1vc7h-mrt-datacite.xml +0 -0
  105. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1w885-mrt-datacite.xml +0 -0
  106. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1wc7t-mrt-datacite.xml +0 -0
  107. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1x59t-mrt-datacite.xml +0 -0
  108. data/spec/data/{dash1-datacite-xml → dash1}/uci-ark+=b7280=d1z594-mrt-datacite.xml +0 -0
  109. data/spec/data/{dash1-datacite-xml → dash1}/ucla-ark+=b5060=d2qr4v2t-mrt-datacite.xml +0 -0
  110. data/spec/data/{dash1-datacite-xml → dash1}/ucla-ark+=b5068=d1cc7x-mrt-datacite.xml +0 -0
  111. data/spec/data/{dash1-datacite-xml → dash1}/ucla-ark+=b5068=d1h59v-mrt-datacite.xml +0 -0
  112. data/spec/data/{dash1-datacite-xml → dash1}/ucla-ark+=b5068=d1rp49-mrt-datacite.xml +0 -0
  113. data/spec/data/{dash1-datacite-xml → dash1}/ucla-ark+=b5068=d1wc7k-mrt-datacite.xml +0 -0
  114. data/spec/data/{dash1-datacite-xml → dash1}/ucm-ark+=13030=m51g217t-mrt-datacite.xml +0 -0
  115. data/spec/data/{dash1-datacite-xml → dash1}/ucm-ark+=b6071=z7wc73-mrt-datacite.xml +0 -0
  116. data/spec/data/{dash1-datacite-xml → dash1}/ucop-ark+=b5060=d8301x-mrt-datacite.xml +0 -0
  117. data/spec/data/{dash1-datacite-xml → dash1}/ucop-ark+=b5060=d86p4w-mrt-datacite.xml +0 -0
  118. data/spec/data/{dash1-datacite-xml → dash1}/ucop-ark+=b5060=d8bc75-mrt-datacite.xml +0 -0
  119. data/spec/data/{dash1-datacite-xml → dash1}/ucop-ark+=b5060=d8g593-mrt-datacite.xml +0 -0
  120. data/spec/data/{dash1-datacite-xml → dash1}/ucop-ark+=b5060=d8h59d-mrt-datacite.xml +0 -0
  121. data/spec/data/{dash1-datacite-xml → dash1}/ucop-ark+=b5060=d8kw2m-mrt-datacite.xml +0 -0
  122. data/spec/data/{dash1-datacite-xml → dash1}/ucop-ark+=b5060=d8rp4v-mrt-datacite.xml +0 -0
  123. data/spec/data/{dash1-datacite-xml → dash1}/ucop-ark+=b5060=d8z59f-mrt-datacite.xml +0 -0
  124. data/spec/data/{dash1-datacite-xml → dash1}/ucsc-ark+=b7291=d11592-mrt-datacite.xml +0 -0
  125. data/spec/data/{dash1-datacite-xml → dash1}/ucsc-ark+=b7291=d17p46-mrt-datacite.xml +0 -0
  126. data/spec/data/{dash1-datacite-xml → dash1}/ucsc-ark+=b7291=d1h59d-mrt-datacite.xml +0 -0
  127. data/spec/data/{dash1-datacite-xml → dash1}/ucsc-ark+=b7291=d1mw2x-mrt-datacite.xml +0 -0
  128. data/spec/data/{dash1-datacite-xml → dash1}/ucsc-ark+=b7291=d1wc74-mrt-datacite.xml +0 -0
  129. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6057cv6-mrt-datacite.xml +0 -0
  130. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6154f00-mrt-datacite.xml +0 -0
  131. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q61z429d-mrt-datacite.xml +0 -0
  132. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q62z13fs-mrt-datacite.xml +0 -0
  133. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q65q4t1r-mrt-datacite.xml +0 -0
  134. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q66q1v54-mrt-datacite.xml +0 -0
  135. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q67p8w9z-mrt-datacite.xml +0 -0
  136. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q68g8hmp-mrt-datacite.xml +0 -0
  137. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6bg2kwf-mrt-datacite.xml +0 -0
  138. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6c8276k-mrt-datacite.xml +0 -0
  139. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6cc0xmh-mrt-datacite.xml +0 -0
  140. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6d798bd-mrt-datacite.xml +0 -0
  141. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6h12zxh-mrt-datacite.xml +0 -0
  142. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6h41pb7-mrt-datacite.xml +0 -0
  143. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6kw5cxv-mrt-datacite.xml +0 -0
  144. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6ms3qnx-mrt-datacite.xml +0 -0
  145. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6mw2f2n-mrt-datacite.xml +0 -0
  146. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6pn93h6-mrt-datacite.xml +0 -0
  147. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6qn64nk-mrt-datacite.xml +0 -0
  148. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6rf5rzx-mrt-datacite.xml +0 -0
  149. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6rn35sz-mrt-datacite.xml +0 -0
  150. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6sf2t3q-mrt-datacite.xml +0 -0
  151. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6td9v7j-mrt-datacite.xml +0 -0
  152. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6w66hpn-mrt-datacite.xml +0 -0
  153. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6x63jt1-mrt-datacite.xml +0 -0
  154. data/spec/data/{dash1-datacite-xml → dash1}/ucsf-ark+=b7272=q6z60kzd-mrt-datacite.xml +0 -0
  155. data/spec/data/datacite-4-synthetic.xml +110 -0
  156. data/spec/data/datacite3/datacite-example-Box_dateCollected_DataCollector-v3.0.xml +46 -0
  157. data/spec/data/datacite3/datacite-example-GeoLocation-v3.0.xml +50 -0
  158. data/spec/data/datacite3/datacite-example-HasMetadata-v3.0.xml +52 -0
  159. data/spec/data/datacite3/datacite-example-ResearchGroup_Methods-v3.0.xml +36 -0
  160. data/spec/data/datacite3/datacite-example-ResourceTypeGeneral_Collection-v3.0.xml +38 -0
  161. data/spec/data/datacite3/datacite-example-complicated-v3.0.xml +48 -0
  162. data/spec/data/datacite3/datacite-example-dataset-v3.0.xml +35 -0
  163. data/spec/data/datacite3/datacite-example-full-v3.1.xml +61 -0
  164. data/spec/data/datacite3/datacite-example-relationTypeIsIdenticalTo-v3.0.xml +48 -0
  165. data/spec/data/datacite3/datacite-example-video-v3.0.xml +26 -0
  166. data/spec/data/datacite3/datacite-example-workflow-v3.0.xml +43 -0
  167. data/spec/data/{metadata.xsd → datacite3/metadata.xsd} +0 -0
  168. data/spec/data/datacite4/datacite-example-Box_dateCollected_DataCollector-v4.0.xml +52 -0
  169. data/spec/data/datacite4/datacite-example-GeoLocation-v4.0.xml +66 -0
  170. data/spec/data/datacite4/datacite-example-HasMetadata-v4.0.xml +62 -0
  171. data/spec/data/datacite4/datacite-example-ResearchGroup_Methods-v4.0.xml +44 -0
  172. data/spec/data/datacite4/datacite-example-ResourceTypeGeneral_Collection-v4.0.xml +52 -0
  173. data/spec/data/datacite4/datacite-example-complicated-v4.0.xml +54 -0
  174. data/spec/data/datacite4/datacite-example-dataset-v4.0.xml +39 -0
  175. data/spec/data/{resource.xml → datacite4/datacite-example-full-v4.0.xml} +14 -4
  176. data/spec/data/{kernel-4.0 → datacite4}/datacite-example-fundingReference-v.4.0.xml +0 -0
  177. data/spec/data/datacite4/datacite-example-relationTypeIsIdenticalTo-v4.0.xml +65 -0
  178. data/spec/data/datacite4/datacite-example-video-v4.0.xml +31 -0
  179. data/spec/data/datacite4/datacite-example-workflow-v4.0.xml +55 -0
  180. data/spec/data/{kernel-4.0 → datacite4}/metadata.xsd +0 -0
  181. data/spec/rspec_custom_matchers.rb +5 -1
  182. data/spec/spec_helper.rb +1 -1
  183. data/spec/unit/datacite/mapping/contributor_spec.rb +7 -0
  184. data/spec/unit/datacite/mapping/creator_spec.rb +92 -0
  185. data/spec/unit/datacite/mapping/date_spec.rb +25 -214
  186. data/spec/unit/datacite/mapping/date_value_spec.rb +143 -0
  187. data/spec/unit/datacite/mapping/description_spec.rb +4 -3
  188. data/spec/unit/datacite/mapping/funding_reference_spec.rb +5 -5
  189. data/spec/unit/datacite/mapping/geo_location_box_spec.rb +0 -36
  190. data/spec/unit/datacite/mapping/geo_location_point_spec.rb +0 -25
  191. data/spec/unit/datacite/mapping/geo_location_polygon_spec.rb +47 -0
  192. data/spec/unit/datacite/mapping/geo_location_spec.rb +153 -6
  193. data/spec/unit/datacite/mapping/identifier_spec.rb +9 -0
  194. data/spec/unit/datacite/mapping/related_identifier_spec.rb +23 -0
  195. data/spec/unit/datacite/mapping/resource_spec.rb +994 -874
  196. data/spec/unit/datacite/mapping/subject_spec.rb +12 -6
  197. data/spec/unit/datacite/mapping/title_spec.rb +20 -6
  198. metadata +320 -278
  199. data/lib/datacite/mapping/nonvalidating.rb +0 -10
  200. data/lib/datacite/mapping/nonvalidating/identifier.rb +0 -40
  201. data/lib/datacite/mapping/nonvalidating/subject.rb +0 -43
  202. data/spec/data/mrt-datacite.xml +0 -61
  203. data/spec/unit/datacite/mapping/log_spec.rb +0 -23
  204. data/spec/unit/datacite/mapping/nonvalidating/identifier_spec.rb +0 -52
  205. data/spec/unit/datacite/mapping/resource_type_spec.rb +0 -68
@@ -32,6 +32,15 @@ module Datacite
32
32
  expect { Identifier.new(value: doi) }.to raise_error(ArgumentError)
33
33
  end
34
34
  end
35
+
36
+ it 'strips' do
37
+ value = '10.14749/1407399495'
38
+ id = Identifier.new(value: "
39
+ #{value}
40
+ ")
41
+ expect(id.value).to eq(value)
42
+ end
43
+
35
44
  end
36
45
 
37
46
  describe '#from_doi' do
@@ -151,6 +151,29 @@ module Datacite
151
151
  expect(id.save_to_xml).to be_xml(expected_xml)
152
152
  end
153
153
  end
154
+
155
+ describe 'IGSN support' do
156
+ attr_reader :igsn_xml
157
+ attr_reader :id
158
+
159
+ before(:each) do
160
+ @igsn_xml = '<relatedIdentifier relatedIdentifierType="IGSN" relationType="References">IECUR0097</relatedIdentifier>'
161
+ @id = RelatedIdentifier.parse_xml(igsn_xml)
162
+ end
163
+
164
+ it 'reads an IGSN' do
165
+ expect(id.identifier_type).to eq(RelatedIdentifierType::IGSN)
166
+ end
167
+
168
+ it 'writes an IGSN' do
169
+ expect(id.save_to_xml).to be_xml(igsn_xml)
170
+ end
171
+
172
+ it 'writes an IGSN as a handle when using DC3 mapping' do
173
+ expected_xml = '<relatedIdentifier relatedIdentifierType="Handle" relationType="References">10273/IECUR0097</relatedIdentifier>'
174
+ expect(id.save_to_xml(mapping: :datacite_3)).to be_xml(expected_xml)
175
+ end
176
+ end
154
177
  end
155
178
  end
156
179
  end
@@ -3,918 +3,1052 @@ require 'spec_helper'
3
3
 
4
4
  module Datacite
5
5
  module Mapping
6
+
6
7
  describe Resource do
7
8
 
8
- before :each do
9
- @id = Identifier.new(value: '10.14749/1407399495')
10
- @creators = [
11
- Creator.new(
12
- name: 'Hedy Lamarr',
13
- identifier: NameIdentifier.new(scheme: 'ISNI', scheme_uri: URI('http://isni.org/'), value: '0000-0001-1690-159X'),
14
- affiliations: ['United Artists', 'Metro-Goldwyn-Mayer']
15
- ),
16
- Creator.new(
17
- name: 'Herschlag, Natalie',
18
- identifier: NameIdentifier.new(scheme: 'ISNI', scheme_uri: URI('http://isni.org/'), value: '0000-0001-0907-8419'),
19
- affiliations: ['Gaumont Buena Vista International', '20th Century Fox']
20
- )
21
- ]
22
- @titles = [
23
- Title.new(value: 'An Account of a Very Odd Monstrous Calf', language: 'en-emodeng'),
24
- Title.new(type: TitleType::SUBTITLE, value: 'And a Contest between Two Artists about Optick Glasses, &c', language: 'en-emodeng')
25
- ]
26
- @publisher = 'California Digital Library'
27
- @pub_year = 2015
28
- end
9
+ attr_reader :identifier
10
+ attr_reader :creators
11
+ attr_reader :titles
12
+ attr_reader :publisher
13
+ attr_reader :publication_year
14
+ attr_reader :args
29
15
 
30
- # TODO: double-check all required/optional attributes
31
-
32
- it 'correctly differentiates required and optional attributes'
33
-
34
- # Required:
35
- #
36
- # <xs:element name="resource">
37
- # <xs:element name="identifier">
38
- # <xs:element name="creators">
39
- # <xs:element name="creator" maxOccurs="unbounded">
40
- # <xs:element name="creatorName">
41
- # <xs:element name="titles">
42
- # <xs:element name="title" maxOccurs="unbounded">
43
- # <xs:element name="publisher">
44
- # <xs:element name="publicationYear">
45
- # <xs:element name="contributorName">
46
-
47
- # Optional:
48
- #
49
- # <xs:element name="nameIdentifier" minOccurs="0">
50
- # <xs:element name="affiliation" minOccurs="0" maxOccurs="unbounded"/>
51
- # <xs:element name="subjects" minOccurs="0">
52
- # <xs:element name="subject" minOccurs="0" maxOccurs="unbounded">
53
- # <xs:element name="contributors" minOccurs="0">
54
- # <xs:element name="contributor" minOccurs="0" maxOccurs="unbounded">
55
- # <xs:element name="nameIdentifier" minOccurs="0">
56
- # <xs:element name="affiliation" minOccurs="0" maxOccurs="unbounded"/>
57
- # <xs:element name="dates" minOccurs="0">
58
- # <xs:element name="date" minOccurs="0" maxOccurs="unbounded">
59
- # <xs:element name="language" type="xs:language" minOccurs="0">
60
- # <xs:element name="resourceType" minOccurs="0">
61
- # <xs:element name="alternateIdentifiers" minOccurs="0">
62
- # <xs:element name="alternateIdentifier" minOccurs="0" maxOccurs="unbounded">
63
- # <xs:element name="relatedIdentifiers" minOccurs="0">
64
- # <xs:element name="relatedIdentifier" minOccurs="0" maxOccurs="unbounded">
65
- # <xs:element name="sizes" minOccurs="0">
66
- # <xs:element name="size" type="xs:string" minOccurs="0" maxOccurs="unbounded">
67
- # <xs:element name="formats" minOccurs="0">
68
- # <xs:element name="format" type="xs:string" minOccurs="0" maxOccurs="unbounded">
69
- # <xs:element name="version" type="xs:string" minOccurs="0">
70
- # <xs:element name="rightsList" minOccurs="0">
71
- # <xs:element name="rights" minOccurs="0" maxOccurs="unbounded">
72
- # <xs:element name="descriptions" minOccurs="0">
73
- # <xs:element name="description" minOccurs="0" maxOccurs="unbounded">
74
- # <xs:element name="br" minOccurs="0" maxOccurs="unbounded">
75
- # <xs:element name="geoLocations" minOccurs="0">
76
- # <xs:element name="geoLocation" minOccurs="0" maxOccurs="unbounded">
77
- # <xs:element name="geoLocationPoint" type="point" minOccurs="0"/>
78
- # <xs:element name="geoLocationBox" type="box" minOccurs="0"/>
79
- # <xs:element name="geoLocationPlace" minOccurs="0"/>
80
-
81
- describe '#initialize' do
82
- it 'sets the identifier' do
83
- resource = Resource.new(
84
- identifier: @id,
85
- creators: @creators,
86
- titles: @titles,
87
- publisher: @publisher,
88
- publication_year: @pub_year
89
- )
90
- expect(resource.identifier).to eq(@id)
91
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
92
- end
93
-
94
- it 'sets the creators' do
95
- resource = Resource.new(
96
- identifier: @id,
97
- creators: @creators,
98
- titles: @titles,
99
- publisher: @publisher,
100
- publication_year: @pub_year
101
- )
102
- expect(resource.creators).to eq(@creators)
103
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
104
- end
105
-
106
- it 'sets the titles' do
107
- resource = Resource.new(
108
- identifier: @id,
109
- creators: @creators,
110
- titles: @titles,
111
- publisher: @publisher,
112
- publication_year: @pub_year
113
- )
114
- expect(resource.titles).to eq(@titles)
115
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
116
- end
117
-
118
- it 'sets the publisher' do
119
- resource = Resource.new(
120
- identifier: @id,
121
- creators: @creators,
122
- titles: @titles,
123
- publisher: @publisher,
124
- publication_year: @pub_year
125
- )
126
- expect(resource.publisher).to eq(@publisher)
127
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
128
- end
129
-
130
- it 'sets the publicationYear' do
131
- resource = Resource.new(
132
- identifier: @id,
133
- creators: @creators,
134
- titles: @titles,
135
- publisher: @publisher,
136
- publication_year: @pub_year
137
- )
138
- expect(resource.publication_year).to eq(@pub_year)
139
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
140
- end
141
-
142
- it 'requires an identifier' do
143
- expect do
144
- Resource.new(
145
- creators: @creators,
146
- titles: @titles,
147
- publisher: @publisher,
148
- publication_year: @pub_year
149
- )
150
- end.to raise_error(ArgumentError)
151
- expect do
152
- Resource.new(
153
- creators: @creators,
154
- titles: @titles,
155
- publisher: @publisher,
156
- publication_year: @pub_year,
157
- identifier: nil
16
+ describe 'fields' do
17
+
18
+ before(:each) do
19
+ @identifier = Identifier.new(value: '10.14749/1407399495')
20
+
21
+ @creators = [
22
+ Creator.new(
23
+ name: 'Hedy Lamarr',
24
+ identifier: NameIdentifier.new(scheme: 'ISNI', scheme_uri: URI('http://isni.org/'), value: '0000-0001-1690-159X'),
25
+ affiliations: ['United Artists', 'Metro-Goldwyn-Mayer']
26
+ ),
27
+ Creator.new(
28
+ name: 'Herschlag, Natalie',
29
+ identifier: NameIdentifier.new(scheme: 'ISNI', scheme_uri: URI('http://isni.org/'), value: '0000-0001-0907-8419'),
30
+ affiliations: ['Gaumont Buena Vista International', '20th Century Fox']
158
31
  )
159
- end.to raise_error(ArgumentError)
32
+ ]
33
+
34
+ @titles = [
35
+ Title.new(value: 'An Account of a Very Odd Monstrous Calf', language: 'en-emodeng'),
36
+ Title.new(type: TitleType::SUBTITLE, value: 'And a Contest between Two Artists about Optick Glasses, &c', language: 'en-emodeng')
37
+ ]
38
+
39
+ @publisher = 'California Digital Library'
40
+ @publication_year = 2015
41
+
42
+ @args = {
43
+ identifier: identifier,
44
+ creators: creators,
45
+ titles: titles,
46
+ publisher: publisher,
47
+ publication_year: publication_year
48
+ }
160
49
  end
161
50
 
162
- it 'requires creators' do
163
- expect do
164
- Resource.new(
165
- identifier: @id,
166
- titles: @titles,
167
- publisher: @publisher,
168
- publication_year: @pub_year
169
- )
170
- end.to raise_error(ArgumentError)
171
- expect do
172
- Resource.new(
173
- identifier: @id,
174
- titles: @titles,
175
- publisher: @publisher,
176
- publication_year: @pub_year,
177
- creators: []
178
- )
179
- end.to raise_error(ArgumentError)
180
- expect do
181
- Resource.new(
182
- identifier: @id,
183
- titles: @titles,
184
- publisher: @publisher,
185
- publication_year: @pub_year,
186
- creators: nil
187
- )
188
- end.to raise_error(ArgumentError)
51
+ describe '#identifier' do
52
+ it 'requires an identifier' do
53
+ args.delete(:identifier)
54
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
55
+ end
56
+
57
+ it 'requires a non-nil identifier' do
58
+ args[:identifier] = nil
59
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
60
+ end
61
+
62
+ it 'can be initialized' do
63
+ resource = Resource.new(args)
64
+ expect(resource.identifier).to eq(identifier)
65
+ end
66
+
67
+ it 'can be set' do
68
+ new_id = Identifier.new(value: '10.1594/WDCC/CCSRNIES_SRES_B2')
69
+ resource = Resource.new(args)
70
+ resource.identifier = new_id
71
+ expect(resource.identifier).to eq(new_id)
72
+ end
189
73
  end
190
74
 
191
- it 'requires titles' do
192
- expect do
193
- Resource.new(
194
- identifier: @id,
195
- creators: @creators,
196
- publisher: @publisher,
197
- publication_year: @pub_year
198
- )
199
- end.to raise_error(ArgumentError)
200
- expect do
201
- Resource.new(
202
- identifier: @id,
203
- creators: @creators,
204
- publisher: @publisher,
205
- publication_year: @pub_year,
206
- titles: nil
207
- )
208
- end.to raise_error(ArgumentError)
209
- expect do
210
- Resource.new(
211
- identifier: @id,
212
- creators: @creators,
213
- publisher: @publisher,
214
- publication_year: @pub_year,
215
- titles: []
216
- )
217
- end.to raise_error(ArgumentError)
75
+ describe '#creators' do
76
+
77
+ it 'requires a creator list' do
78
+ args.delete(:creators)
79
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
80
+ end
81
+
82
+ it 'requires a non-nil creator list' do
83
+ args[:creators] = nil
84
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
85
+ end
86
+
87
+ it 'requires a non-empty creator list' do
88
+ args[:creators] = []
89
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
90
+ end
91
+
92
+ it 'can be initialized' do
93
+ resource = Resource.new(args)
94
+ expect(resource.creators).to eq(creators)
95
+ end
96
+
97
+ it 'can be set' do
98
+ new_creators = [Creator.new(
99
+ name: 'Danica McKellar',
100
+ identifier: NameIdentifier.new(scheme: 'ISNI', scheme_uri: URI('http://isni.org/'), value: '0000 0001 1678 4522'),
101
+ affiliations: ['Disney–ABC Television Group']
102
+ )]
103
+ resource = Resource.new(args)
104
+ resource.creators = new_creators
105
+ expect(resource.creators).to eq(new_creators)
106
+ end
107
+
108
+ describe 'creator convenience methods' do
109
+ describe '#creator_names' do
110
+ it 'extracts the creator names' do
111
+ resource = Resource.new(args)
112
+ expect(resource.creator_names)
113
+ .to eq(['Hedy Lamarr', 'Herschlag, Natalie'])
114
+ end
115
+ end
116
+
117
+ describe '#creator_affiliations' do
118
+ it 'extracts the creator affiliations' do
119
+ resource = Resource.new(args)
120
+ expect(resource.creator_affiliations)
121
+ .to eq([
122
+ ['United Artists', 'Metro-Goldwyn-Mayer'],
123
+ ['Gaumont Buena Vista International', '20th Century Fox']
124
+ ])
125
+ end
126
+ end
127
+ end
218
128
  end
219
129
 
220
- it 'requires a publisher' do
221
- expect do
222
- Resource.new(
223
- identifier: @id,
224
- creators: @creators,
225
- titles: @titles,
226
- publication_year: @pub_year
227
- )
228
- end.to raise_error(ArgumentError)
229
- expect do
230
- Resource.new(
231
- identifier: @id,
232
- creators: @creators,
233
- titles: @titles,
234
- publication_year: @pub_year,
235
- publisher: nil
236
- )
237
- end.to raise_error(ArgumentError)
238
- expect do
239
- Resource.new(
240
- identifier: @id,
241
- creators: @creators,
242
- titles: @titles,
243
- publication_year: @pub_year,
244
- publisher: []
245
- )
246
- end.to raise_error(ArgumentError)
247
- expect do
248
- Resource.new(
249
- identifier: @id,
250
- creators: @creators,
251
- titles: @titles,
252
- publication_year: @pub_year,
253
- publisher: ''
254
- )
255
- end.to raise_error(ArgumentError)
130
+ describe '#titles' do
131
+ it 'requires a title list' do
132
+ args.delete(:titles)
133
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
134
+ end
135
+
136
+ it 'requires a non-nil title list' do
137
+ args[:titles] = nil
138
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
139
+ end
140
+
141
+ it 'requires a non-empty title list' do
142
+ args[:titles] = []
143
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
144
+ end
145
+
146
+ it 'can be initialized' do
147
+ resource = Resource.new(args)
148
+ expect(resource.titles).to eq(titles)
149
+ end
150
+
151
+ it 'can be set' do
152
+ new_titles = [Title.new(
153
+ language: 'en-emodeng',
154
+ type: TitleType::SUBTITLE,
155
+ value: 'Together with an Appendix of the Same, Containing an Answer to Some Objections, Made by Severall Persons against That Hypothesis'
156
+ )]
157
+ resource = Resource.new(args)
158
+ resource.titles = new_titles
159
+ expect(resource.titles).to eq(new_titles)
160
+ end
161
+
256
162
  end
257
163
 
258
- it 'requires a publicationYear' do
259
- expect do
260
- Resource.new(
261
- identifier: @id,
262
- creators: @creators,
263
- titles: @titles,
264
- publisher: @publisher
265
- )
266
- end.to raise_error(ArgumentError)
267
- expect do
268
- Resource.new(
269
- identifier: @id,
270
- creators: @creators,
271
- titles: @titles,
272
- publisher: @publisher,
273
- publication_year: nil
274
- )
275
- end.to raise_error(ArgumentError)
276
- expect do
277
- Resource.new(
278
- identifier: @id,
279
- creators: @creators,
280
- titles: @titles,
281
- publisher: @publisher,
282
- publication_year: -1
283
- )
284
- end.to raise_error(ArgumentError)
285
- expect do
286
- Resource.new(
287
- identifier: @id,
288
- creators: @creators,
289
- titles: @titles,
290
- publisher: @publisher,
291
- publication_year: 999
292
- )
293
- end.to raise_error(ArgumentError)
294
- expect do
295
- Resource.new(
296
- identifier: @id,
297
- creators: @creators,
298
- titles: @titles,
299
- publisher: @publisher,
300
- publication_year: 10_000
301
- )
302
- end.to raise_error(ArgumentError)
164
+ describe '#publisher' do
165
+ it 'requires a publisher' do
166
+ args.delete(:publisher)
167
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
168
+ end
169
+ it 'requires a non-nil publisher' do
170
+ args[:publisher] = nil
171
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
172
+ end
173
+ it 'requires a non-blank publisher' do
174
+ args[:publisher] = "\n \n"
175
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
176
+ end
177
+ it 'can be initialized' do
178
+ resource = Resource.new(args)
179
+ expect(resource.publisher).to eq(publisher)
180
+ end
181
+ it 'can be set' do
182
+ new_publisher = 'University of California'
183
+ resource = Resource.new(args)
184
+ resource.publisher = new_publisher
185
+ expect(resource.publisher).to eq(new_publisher)
186
+ end
187
+ it 'strips on initialization' do
188
+ args[:publisher] = '
189
+ University of California
190
+ '
191
+ resource = Resource.new(args)
192
+ expect(resource.publisher).to eq('University of California')
193
+ end
194
+ it 'strips on set' do
195
+ resource = Resource.new(args)
196
+ resource.publisher = '
197
+ University of California
198
+ '
199
+ expect(resource.publisher).to eq('University of California')
200
+ end
303
201
  end
304
202
 
305
- it 'allows subjects' do
306
- subjects = [
307
- Subject.new(
308
- language: 'en-us',
309
- scheme: 'LCSH',
310
- scheme_uri: URI('http://id.loc.gov/authorities/subjects'),
311
- value: 'Mammals--Embryology'
312
- ),
313
- Subject.new(
314
- language: 'fr',
315
- scheme: 'dewey',
316
- scheme_uri: URI('http://dewey.info/'),
317
- value: '571.8 Croissance, développement, reproduction biologique (fécondation, sexualité)'
318
- )
319
- ]
320
- resource = Resource.new(
321
- identifier: @id,
322
- creators: @creators,
323
- titles: @titles,
324
- publisher: @publisher,
325
- publication_year: @pub_year,
326
- subjects: subjects
327
- )
328
- expect(resource.subjects).to eq(subjects)
329
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
330
- end
331
-
332
- it 'allows dates' do
333
- dates = [
334
- Date.new(value: DateTime.new(1914, 8, 4, 11, 01, 6.0123, '+1'), type: DateType::AVAILABLE),
335
- Date.new(value: '1914-08-04T11:01:06.0123+01:00', type: DateType::AVAILABLE)
336
- ]
337
- resource = Resource.new(
338
- identifier: @id,
339
- creators: @creators,
340
- titles: @titles,
341
- publisher: @publisher,
342
- publication_year: @pub_year,
343
- dates: dates
344
- )
345
- expect(resource.dates).to eq(dates)
346
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
347
- end
348
-
349
- it 'allows a language' do
350
- resource = Resource.new(
351
- identifier: @id,
352
- creators: @creators,
353
- titles: @titles,
354
- publisher: @publisher,
355
- publication_year: @pub_year,
356
- language: 'en-emodeng'
357
- )
358
- expect(resource.language).to eq('en-emodeng')
359
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
360
- end
361
-
362
- it 'allows alternate identifiers' do
363
- alternate_identifiers = [
364
- AlternateIdentifier.new(type: 'URL', value: 'http://example.org'),
365
- AlternateIdentifier.new(type: 'URL', value: 'http://example.com')
366
- ]
367
- resource = Resource.new(
368
- identifier: @id,
369
- creators: @creators,
370
- titles: @titles,
371
- publisher: @publisher,
372
- publication_year: @pub_year,
373
- alternate_identifiers: alternate_identifiers
374
- )
375
- expect(resource.alternate_identifiers).to eq(alternate_identifiers)
376
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
377
- end
378
-
379
- it 'allows sizes' do
380
- sizes = ['2 petabytes', '2048 TB']
381
- resource = Resource.new(
382
- identifier: @id,
383
- creators: @creators,
384
- titles: @titles,
385
- publisher: @publisher,
386
- publication_year: @pub_year,
387
- sizes: sizes
388
- )
389
- expect(resource.sizes).to eq(sizes)
390
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
391
- end
392
-
393
- it 'allows related identifiers' do
394
- related_identifiers = [
395
- RelatedIdentifier.new(
396
- identifier_type: RelatedIdentifierType::URL,
397
- relation_type: RelationType::HAS_METADATA,
398
- related_metadata_scheme: 'citeproc+json',
399
- scheme_type: 'Turtle',
400
- scheme_uri: URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json'),
401
- value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full'
402
- ),
403
- RelatedIdentifier.new(
404
- identifier_type: RelatedIdentifierType::ARXIV,
405
- relation_type: RelationType::IS_REVIEWED_BY,
406
- value: 'arXiv:0706.0001'
407
- )
408
- ]
409
- resource = Resource.new(
410
- identifier: @id,
411
- creators: @creators,
412
- titles: @titles,
413
- publisher: @publisher,
414
- publication_year: @pub_year,
415
- related_identifiers: related_identifiers
416
- )
417
- expect(resource.related_identifiers).to eq(related_identifiers)
418
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
419
- end
420
-
421
- it 'allows formats' do
422
- formats = %w(application/xml text/html)
423
- resource = Resource.new(
424
- identifier: @id,
425
- creators: @creators,
426
- titles: @titles,
427
- publisher: @publisher,
428
- publication_year: @pub_year,
429
- formats: formats
430
- )
431
- expect(resource.formats).to eq(formats)
432
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
433
- end
434
-
435
- it 'allows a version' do
436
- version = '3.1'
437
- resource = Resource.new(
438
- identifier: @id,
439
- creators: @creators,
440
- titles: @titles,
441
- publisher: @publisher,
442
- publication_year: @pub_year,
443
- version: version
444
- )
445
- expect(resource.version).to eq(version)
446
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
447
- end
448
-
449
- it 'allows rights' do
450
- rights_list = [
451
- Rights.new(value: 'CC0 1.0 Universal', uri: URI('http://creativecommons.org/publicdomain/zero/1.0/')),
452
- Rights.new(value: 'This work is free of known copyright restrictions.', uri: URI('http://creativecommons.org/publicdomain/mark/1.0/'))
453
- ]
454
- resource = Resource.new(
455
- identifier: @id,
456
- creators: @creators,
457
- titles: @titles,
458
- publisher: @publisher,
459
- publication_year: @pub_year,
460
- rights_list: rights_list
461
- )
462
- expect(resource.rights_list).to eq(rights_list)
463
- expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
203
+ describe '#publication_year' do
204
+ it 'requires a publication_year' do
205
+ args.delete(:publication_year)
206
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
207
+ end
208
+ it 'requires a non-nil publication_year' do
209
+ args[:publication_year] = nil
210
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
211
+ end
212
+ it 'requires a four-digit publication_year' do
213
+ args[:publication_year] = 999
214
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
215
+ args[:publication_year] = 10_000
216
+ expect { Resource.new(args) }.to raise_error(ArgumentError)
217
+ end
218
+ it 'can be initialized' do
219
+ resource = Resource.new(args)
220
+ expect(resource.publication_year).to eq(publication_year)
221
+ end
222
+ it 'can be set' do
223
+ new_pub_year = 1963
224
+ resource = Resource.new(args)
225
+ resource.publication_year = new_pub_year
226
+ expect(resource.publication_year).to eq(new_pub_year)
227
+ end
228
+ it 'converts strings to integers' do
229
+ new_pub_year = 1963
230
+ resource = Resource.new(args)
231
+ resource.publication_year = "#{new_pub_year}"
232
+ expect(resource.publication_year).to eq(new_pub_year)
233
+ end
464
234
  end
465
- end
466
235
 
467
- describe '#parse_xml' do
468
- before(:each) do
469
- identifier = Identifier.new(value: '10.5072/example-full').save_to_xml
236
+ describe '#subjects' do
237
+ it 'defaults to empty' do
238
+ resource = Resource.new(args)
239
+ expect(resource.subjects).to eq([])
240
+ end
470
241
 
471
- creators = REXML::Element.new('creators')
472
- creators.add_element(Creator.new(
473
- name: 'Miller, Elizabeth',
474
- identifier: NameIdentifier.new(scheme: 'ORCID', scheme_uri: URI('http://orcid.org'), value: '0000-0001-5000-0007'),
475
- affiliations: ['DataCite']
476
- ).save_to_xml)
242
+ describe 'subjects:' do
243
+ it 'can be initialized' do
244
+ subjects = [
245
+ Subject.new(
246
+ language: 'en-us',
247
+ scheme: 'LCSH',
248
+ scheme_uri: URI('http://identifier.loc.gov/authorities/subjects'),
249
+ value: 'Mammals--Embryology'
250
+ ),
251
+ Subject.new(
252
+ language: 'fr',
253
+ scheme: 'dewey',
254
+ scheme_uri: URI('http://dewey.info/'),
255
+ value: '571.8 Croissance, développement, reproduction biologique (fécondation, sexualité)'
256
+ )
257
+ ]
258
+ args[:subjects] = subjects
259
+ resource = Resource.new(args)
260
+ expect(resource.subjects).to eq(subjects)
261
+ end
262
+ it 'can\'t be initialized to nil' do
263
+ args[:subjects] = nil
264
+ resource = Resource.new(args)
265
+ expect(resource.subjects).to eq([])
266
+ end
477
267
 
478
- titles = REXML::Element.new('titles')
479
- titles.add_element(Title.new(
480
- language: 'en-us',
481
- value: 'Full DataCite XML Example'
482
- ).save_to_xml)
483
- titles.add_element(Title.new(
484
- language: 'en-us',
485
- type: TitleType::SUBTITLE,
486
- value: 'Demonstration of DataCite Properties.'
487
- ).save_to_xml)
268
+ it 'ignores subjects without values' do
269
+ subjects = [
270
+ Subject.allocate,
271
+ Subject.new(value: 'Mammals--Embryology'),
272
+ Subject.allocate
273
+ ]
274
+ args[:subjects] = subjects
275
+ resource = Resource.new(args)
276
+ expect(resource.subjects).to eq([subjects[1]])
277
+ end
278
+ end
488
279
 
489
- publisher = REXML::Element.new('publisher')
490
- publisher.text = 'DataCite'
280
+ describe '#subjects=' do
281
+ it 'can be set' do
282
+ subjects = [
283
+ Subject.new(
284
+ language: 'en-us',
285
+ scheme: 'LCSH',
286
+ scheme_uri: URI('http://identifier.loc.gov/authorities/subjects'),
287
+ value: 'Mammals--Embryology'
288
+ ),
289
+ Subject.new(
290
+ language: 'fr',
291
+ scheme: 'dewey',
292
+ scheme_uri: URI('http://dewey.info/'),
293
+ value: '571.8 Croissance, développement, reproduction biologique (fécondation, sexualité)'
294
+ )
295
+ ]
296
+ resource = Resource.new(args)
297
+ resource.subjects = subjects
298
+ expect(resource.subjects).to eq(subjects)
299
+ end
300
+ it 'can\'t be set to nil' do
301
+ resource = Resource.new(args)
302
+ resource.subjects = nil
303
+ expect(resource.subjects).to eq([])
304
+ end
305
+ it 'ignores subjects without values' do
306
+ subjects = [
307
+ Subject.allocate,
308
+ Subject.new(value: 'Mammals--Embryology'),
309
+ Subject.allocate
310
+ ]
311
+ resource = Resource.new(args)
312
+ resource.subjects = subjects
313
+ expect(resource.subjects).to eq([subjects[1]])
314
+ end
315
+ end
316
+ end
491
317
 
492
- publication_year = REXML::Element.new('publicationYear')
493
- publication_year.text = '2014'
318
+ describe '#funding_references' do
319
+ it 'defaults to empty' do
320
+ resource = Resource.new(args)
321
+ expect(resource.funding_references).to eq([])
322
+ end
494
323
 
495
- resource = REXML::Element.new('resource')
496
- resource.add_namespace('http://datacite.org/schema/kernel-3')
497
- resource.add_namespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance')
498
- resource.add_attribute('xsi:schemaLocation', 'http://datacite.org/schema/kernel-3 http://schema.datacite.org/meta/kernel-3/metadata.xsd')
499
- resource.add_element(identifier)
500
- resource.add_element(creators)
501
- resource.add_element(titles)
502
- resource.add_element(publisher)
503
- resource.add_element(publication_year)
324
+ describe 'funding_references:' do
325
+ it 'can be initialized' do
326
+ funding_references = [
327
+ FundingReference.new(name: 'Ministry of Magic', award_number: '9¾'),
328
+ FundingReference.new(name: 'НИИЧАВО', award_number: '164070')
329
+ ]
330
+ args[:funding_references] = funding_references
331
+ resource = Resource.new(args)
332
+ expect(resource.funding_references).to eq(funding_references)
333
+ end
334
+ it 'can\'t be initialized to nil' do
335
+ args[:funding_references] = nil
336
+ resource = Resource.new(args)
337
+ expect(resource.funding_references).to eq([])
338
+ end
339
+ end
504
340
 
505
- @required_xml = resource
341
+ describe '#funding_references=' do
342
+ it 'can be set' do
343
+ resource = Resource.new(args)
344
+ funding_references = [
345
+ FundingReference.new(name: 'Ministry of Magic', award_number: '9¾'),
346
+ FundingReference.new(name: 'НИИЧАВО', award_number: '164070')
347
+ ]
348
+ resource.funding_references = funding_references
349
+ expect(resource.funding_references).to eq(funding_references)
350
+ end
351
+ it 'can\'t be set to nil' do
352
+ resource = Resource.new(args)
353
+ resource.funding_references = nil
354
+ expect(resource.funding_references).to eq([])
355
+ end
356
+ end
506
357
  end
507
358
 
508
- it 'parses a resource with only required attributes' do
509
- resource = Resource.parse_xml(@required_xml)
510
- expect(resource.language).to eq('en')
359
+ describe '#language' do
360
+ it 'defaults to nil' do
361
+ resource = Resource.new(args)
362
+ expect(resource.language).to be_nil
363
+ end
364
+
365
+ it 'can be initialized' do
366
+ args[:language] = 'en-emodeng'
367
+ resource = Resource.new(args)
368
+ expect(resource.language).to eq('en-emodeng')
369
+ end
370
+
371
+ it 'can be set' do
372
+ resource = Resource.new(args)
373
+ resource.language = 'en-emodeng'
374
+ expect(resource.language).to eq('en-emodeng')
375
+ end
511
376
  end
512
377
 
513
- it 'correctly differentiates required and optional attributes'
378
+ describe '#contributors' do
379
+
380
+ it 'defaults to empty' do
381
+ resource = Resource.new(args)
382
+ expect(resource.funding_references).to eq([])
383
+ end
384
+
385
+ describe 'contributors:' do
386
+ it 'can be initialized' do
387
+ contributors = [
388
+ Contributor.new(name: 'Hershlag, Natalie', type: ContributorType::PROJECT_MEMBER),
389
+ Contributor.new(name: 'Hedy Lamarr', type: ContributorType::RESEARCHER)
390
+ ]
391
+ args[:contributors] = contributors
392
+ resource = Resource.new(args)
393
+ expect(resource.contributors).to eq(contributors)
394
+ end
395
+ it 'can\'t be initialized to nil' do
396
+ args[:contributors] = nil
397
+ resource = Resource.new(args)
398
+ expect(resource.contributors).to eq([])
399
+ end
400
+ end
401
+
402
+ describe '#contributors=' do
403
+ it 'can be set' do
404
+ resource = Resource.new(args)
405
+ contributors = [
406
+ Contributor.new(name: 'Hershlag, Natalie', type: ContributorType::PROJECT_MEMBER),
407
+ Contributor.new(name: 'Hedy Lamarr', type: ContributorType::RESEARCHER)
408
+ ]
409
+ resource.contributors = contributors
410
+ expect(resource.contributors).to eq(contributors)
411
+ end
412
+ it 'can\'t be set to nil' do
413
+ resource = Resource.new(args)
414
+ resource.contributors = nil
415
+ expect(resource.contributors).to eq([])
416
+ end
417
+ end
418
+
419
+ describe 'contributor convenience methods' do
420
+ before(:each) do
421
+ @resource = Resource.new(args)
422
+ @funder = Contributor.new(
423
+ name: 'The Ministry of Magic',
424
+ identifier: NameIdentifier.new(
425
+ scheme: 'IATI',
426
+ scheme_uri: URI('http://iatistandard.org/201/codelists/OrganisationIdentifier/'),
427
+ value: 'GR-9¾'
428
+ ),
429
+ type: ContributorType::FUNDER)
430
+ @resource.contributors << @funder
431
+ end
514
432
 
515
- it 'parses a Datacite 4.0 document with FundingReference' do
516
- resource = Resource.parse_xml(File.read('spec/data/kernel-4.0/datacite-example-fundingReference-v.4.0.xml'))
517
- funding_references = resource.funding_references
518
- expect(funding_references.size).to eq(2)
519
- funding_references.each do |fref|
520
- expect(fref).to be_a(FundingReference)
433
+ describe 'funder_contrib' do
434
+ it 'extracts the funder contrib' do
435
+ expect(@resource.funder_contrib).to eq(@funder)
436
+ end
437
+ end
438
+
439
+ describe 'funder_name' do
440
+ it 'extracts the funder name' do
441
+ expect(@resource.funder_name).to eq(@funder.name)
442
+ end
443
+ end
444
+
445
+ describe 'funder_id' do
446
+ it 'extracts the funder id' do
447
+ expect(@resource.funder_id).to eq(@funder.identifier)
448
+ end
449
+ end
450
+
451
+ describe 'funder_id_value' do
452
+ it 'extracts the funder id value' do
453
+ expect(@resource.funder_id_value).to eq(@funder.identifier.value)
454
+ end
455
+ end
521
456
  end
522
457
  end
523
- end
524
458
 
525
- describe '#save_to_xml' do
526
- it 'sets the namespace to http://datacite.org/schema/kernel-3'
527
- it "doesn't clobber the namespace on the various xml:lang attributes"
459
+ describe '#dates' do
460
+ it 'defaults to empty' do
461
+ resource = Resource.new(args)
462
+ expect(resource.funding_references).to eq([])
463
+ end
528
464
 
529
- # TODO: make this work; maybe it's the language that's the issue?
530
- xit 'round-trips a Datacite 4.0 document with FundingReference' do
531
- xml_text = File.read('spec/data/kernel-4.0/datacite-example-fundingReference-v.4.0.xml')
532
- resource = Resource.parse_xml(xml_text)
533
- saved_xml = resource.save_to_xml
534
- expect(saved_xml).to be_xml(xml_text)
465
+ describe 'dates:' do
466
+ it 'can be initialized' do
467
+ dates = [
468
+ Date.new(value: DateTime.new(1914, 8, 4, 11, 01, 6.0123, '+1'), type: DateType::AVAILABLE),
469
+ Date.new(value: '1914-08-04T11:01:06.0123+01:00', type: DateType::AVAILABLE)
470
+ ]
471
+ args[:dates] = dates
472
+ resource = Resource.new(args)
473
+ expect(resource.dates).to eq(dates)
474
+ end
475
+ it 'can\'t be initialized to nil' do
476
+ args[:dates] = nil
477
+ resource = Resource.new(args)
478
+ expect(resource.dates).to eq([])
479
+ end
480
+ end
481
+
482
+ describe '#dates=' do
483
+ it 'can be set' do
484
+ resource = Resource.new(args)
485
+ dates = [
486
+ Date.new(value: DateTime.new(1914, 8, 4, 11, 01, 6.0123, '+1'), type: DateType::AVAILABLE),
487
+ Date.new(value: '1914-08-04T11:01:06.0123+01:00', type: DateType::AVAILABLE)
488
+ ]
489
+ resource.dates = dates
490
+ expect(resource.dates).to eq(dates)
491
+ end
492
+ it 'can\'t be set to nil' do
493
+ resource = Resource.new(args)
494
+ resource.dates = nil
495
+ expect(resource.dates).to eq([])
496
+ end
497
+ end
535
498
  end
536
- end
537
499
 
538
- describe 'identifier' do
539
- it 'returns the identifier'
540
- end
500
+ describe '#resource_type' do
501
+ it 'can be initialized' do
502
+ resource_type = ResourceType.new(resource_type_general: ResourceTypeGeneral::DATASET, value: 'Dataset')
503
+ args[:resource_type] = resource_type
504
+ resource = Resource.new(args)
505
+ expect(resource.resource_type).to eq(resource_type)
506
+ end
541
507
 
542
- describe 'identifier=' do
543
- it 'sets the identifier'
544
- it 'rejects nil'
545
- end
508
+ it 'can be set' do
509
+ resource_type = ResourceType.new(resource_type_general: ResourceTypeGeneral::DATASET, value: 'Dataset')
510
+ resource = Resource.new(args)
511
+ resource.resource_type = resource_type
512
+ expect(resource.resource_type).to eq(resource_type)
513
+ end
514
+ end
546
515
 
547
- describe 'creators' do
548
- it 'returns the creator list'
549
- it 'returns an editable list'
550
- end
516
+ describe '#alternate_identifiers' do
517
+ it 'defaults to empty' do
518
+ resource = Resource.new(args)
519
+ expect(resource.alternate_identifiers).to eq([])
520
+ end
551
521
 
552
- describe 'creators=' do
553
- it 'overwrites the creator list'
554
- it 'requires at least one creator'
555
- end
522
+ describe 'alternate_identifiers:' do
523
+ it 'can be initialized' do
524
+ alternate_identifiers = [
525
+ AlternateIdentifier.new(type: 'URL', value: 'http://example.org'),
526
+ AlternateIdentifier.new(type: 'URL', value: 'http://example.com')
527
+ ]
528
+ args[:alternate_identifiers] = alternate_identifiers
529
+ resource = Resource.new(args)
530
+ expect(resource.alternate_identifiers).to eq(alternate_identifiers)
531
+ end
532
+ it 'can\'t be initialized to nil' do
533
+ args[:alternate_identifiers] = nil
534
+ resource = Resource.new(args)
535
+ expect(resource.alternate_identifiers).to eq([])
536
+ end
537
+ end
556
538
 
557
- describe 'titles' do
558
- it 'returns the title list'
559
- it 'returns an editable list'
560
- end
539
+ describe '#alternate_identifiers=' do
540
+ it 'can be set' do
541
+ resource = Resource.new(args)
542
+ alternate_identifiers = [
543
+ AlternateIdentifier.new(type: 'URL', value: 'http://example.org'),
544
+ AlternateIdentifier.new(type: 'URL', value: 'http://example.com')
545
+ ]
546
+ resource.alternate_identifiers = alternate_identifiers
547
+ expect(resource.alternate_identifiers).to eq(alternate_identifiers)
548
+ end
549
+ it 'can\'t be set to nil' do
550
+ resource = Resource.new(args)
551
+ resource.alternate_identifiers = nil
552
+ expect(resource.alternate_identifiers).to eq([])
553
+ end
554
+ end
555
+ end
561
556
 
562
- describe 'titles=' do
563
- it 'overwrites the title list'
564
- it 'requires at least one title'
565
- end
557
+ describe '#related_identifiers' do
558
+ it 'defaults to empty' do
559
+ resource = Resource.new(args)
560
+ expect(resource.related_identifiers).to eq([])
561
+ end
566
562
 
567
- describe 'publisher' do
568
- it 'returns the publisher'
569
- end
563
+ describe 'related_identifiers:' do
564
+ it 'can be initialized' do
565
+ related_identifiers = [
566
+ RelatedIdentifier.new(
567
+ identifier_type: RelatedIdentifierType::URL,
568
+ relation_type: RelationType::HAS_METADATA,
569
+ related_metadata_scheme: 'citeproc+json',
570
+ scheme_type: 'Turtle',
571
+ scheme_uri: URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json'),
572
+ value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full'
573
+ ),
574
+ RelatedIdentifier.new(
575
+ identifier_type: RelatedIdentifierType::ARXIV,
576
+ relation_type: RelationType::IS_REVIEWED_BY,
577
+ value: 'arXiv:0706.0001'
578
+ )
579
+ ]
580
+ args[:related_identifiers] = related_identifiers
581
+ resource = Resource.new(args)
582
+ expect(resource.related_identifiers).to eq(related_identifiers)
583
+ end
584
+ it 'can\'t be initialized to nil' do
585
+ args[:related_identifiers] = nil
586
+ resource = Resource.new(args)
587
+ expect(resource.related_identifiers).to eq([])
588
+ end
589
+ end
570
590
 
571
- describe 'publisher=' do
572
- it 'sets the publisher'
573
- it 'rejects nil'
574
- it 'rejects the empty string'
575
- end
591
+ describe '#related_identifiers=' do
592
+ it 'can be set' do
593
+ resource = Resource.new(args)
594
+ related_identifiers = [
595
+ RelatedIdentifier.new(
596
+ identifier_type: RelatedIdentifierType::URL,
597
+ relation_type: RelationType::HAS_METADATA,
598
+ related_metadata_scheme: 'citeproc+json',
599
+ scheme_type: 'Turtle',
600
+ scheme_uri: URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json'),
601
+ value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full'
602
+ ),
603
+ RelatedIdentifier.new(
604
+ identifier_type: RelatedIdentifierType::ARXIV,
605
+ relation_type: RelationType::IS_REVIEWED_BY,
606
+ value: 'arXiv:0706.0001'
607
+ )
608
+ ]
609
+ resource.related_identifiers = related_identifiers
610
+ expect(resource.related_identifiers).to eq(related_identifiers)
611
+ end
612
+ it 'can\'t be set to nil' do
613
+ resource = Resource.new(args)
614
+ resource.related_identifiers = nil
615
+ expect(resource.related_identifiers).to eq([])
616
+ end
617
+ end
618
+ end
576
619
 
577
- describe 'publication_year' do
578
- it 'returns the publication year'
579
- it 'rejects nil'
580
- it 'accepts only 4-digit integers'
581
- end
620
+ describe '#sizes' do
621
+ it 'defaults to empty' do
622
+ resource = Resource.new(args)
623
+ expect(resource.sizes).to eq([])
624
+ end
582
625
 
583
- describe 'publication_year=' do
584
- it 'sets the publication year'
585
- end
626
+ describe 'sizes:' do
627
+ it 'can be initialized' do
628
+ sizes = %w(48K 128K)
629
+ args[:sizes] = sizes
630
+ resource = Resource.new(args)
631
+ expect(resource.sizes).to eq(sizes)
632
+ end
633
+ it 'can\'t be initialized to nil' do
634
+ args[:sizes] = nil
635
+ resource = Resource.new(args)
636
+ expect(resource.sizes).to eq([])
637
+ end
638
+ end
586
639
 
587
- describe 'subjects' do
588
- it 'returns the subject list'
589
- it 'returns an editable list'
590
-
591
- describe 'nonvalidating mode' do
592
- it 'filters out empty subjects' do
593
- xml_text = "<resource xsi:schemaLocation='http://datacite.org/schema/kernel-3 http://schema.datacite.org/meta/kernel-3/metadata.xsd' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://datacite.org/schema/kernel-3'>
594
- <identifier identifierType='DOI'>10.14749/1407399495</identifier>
595
- <creators>
596
- <creator>
597
- <creatorName>Hedy Lamarr</creatorName>
598
- </creator>
599
- <creator>
600
- <creatorName>Herschlag, Natalie</creatorName>
601
- </creator>
602
- </creators>
603
- <titles>
604
- <title>An Account of a Very Odd Monstrous Calf</title>
605
- </titles>
606
- <publisher>California Digital Library</publisher>
607
- <publicationYear>2015</publicationYear>
608
- <subjects>
609
- <subject subjectScheme='LCSH' schemeURI='http://id.loc.gov/authorities/subjects' xml:lang='en-us'>Mammals--Embryology</subject>
610
- <subject/>
611
- <subject subjectScheme='dewey' schemeURI='http://dewey.info/' xml:lang='fr'>571.8 Croissance, développement, reproduction biologique (fécondation, sexualité)</subject>
612
- <subject subjectScheme='dewey' schemeURI='http://dewey.info/'></subject>
613
- </subjects>
614
- <language>en</language>
615
- </resource>"
616
- resource = Resource.parse_xml(xml_text, mapping: :nonvalidating)
617
-
618
- expected = [
619
- Subject.new(
620
- language: 'en-us',
621
- scheme: 'LCSH',
622
- scheme_uri: URI('http://id.loc.gov/authorities/subjects'),
623
- value: 'Mammals--Embryology'
624
- ),
625
- Subject.new(
626
- language: 'fr',
627
- scheme: 'dewey',
628
- scheme_uri: URI('http://dewey.info/'),
629
- value: '571.8 Croissance, développement, reproduction biologique (fécondation, sexualité)'
630
- )
631
- ]
632
-
633
- subjects = resource.subjects
634
- expect(subjects.size).to eq(expected.size)
635
- expected.each_with_index do |ex, i|
636
- expect(subjects[i].language).to eq(ex.language)
637
- expect(subjects[i].scheme).to eq(ex.scheme)
638
- expect(subjects[i].scheme_uri).to eq(ex.scheme_uri)
639
- expect(subjects[i].value).to eq(ex.value)
640
+ describe '#sizes=' do
641
+ it 'can be set' do
642
+ sizes = %w(48K 128K)
643
+ resource = Resource.new(args)
644
+ resource.sizes = sizes
645
+ expect(resource.sizes).to eq(sizes)
646
+ end
647
+ it 'can\'t be set to nil' do
648
+ resource = Resource.new(args)
649
+ resource.sizes = nil
650
+ expect(resource.sizes).to eq([])
640
651
  end
641
652
  end
642
653
  end
643
654
 
644
- end
655
+ describe '#formats' do
656
+ it 'defaults to empty' do
657
+ resource = Resource.new(args)
658
+ expect(resource.formats).to eq([])
659
+ end
645
660
 
646
- describe 'subjects=' do
647
- it 'overwrites the subject list'
648
- it 'accepts an empty list'
649
- end
661
+ describe 'formats:' do
662
+ it 'can be initialized' do
663
+ formats = %w(D64 DSK)
664
+ args[:formats] = formats
665
+ resource = Resource.new(args)
666
+ expect(resource.formats).to eq(formats)
667
+ end
668
+ it 'can\'t be initialized to nil' do
669
+ args[:formats] = nil
670
+ resource = Resource.new(args)
671
+ expect(resource.formats).to eq([])
672
+ end
673
+ end
650
674
 
651
- describe 'dates' do
652
- it 'returns the date list'
653
- it 'returns an editable list'
654
- end
675
+ describe '#formats=' do
676
+ it 'can be set' do
677
+ formats = %w(D64 DSK)
678
+ resource = Resource.new(args)
679
+ resource.formats = formats
680
+ expect(resource.formats).to eq(formats)
681
+ end
682
+ it 'can\'t be set to nil' do
683
+ resource = Resource.new(args)
684
+ resource.formats = nil
685
+ expect(resource.formats).to eq([])
686
+ end
687
+ end
688
+ end
655
689
 
656
- describe 'dates=' do
657
- it 'overwrites the date list'
658
- it 'accepts an empty list'
659
- end
690
+ describe '#version' do
691
+ it 'defaults to nil' do
692
+ resource = Resource.new(args)
693
+ expect(resource.version).to be_nil
694
+ end
695
+ it 'can be initialized' do
696
+ args[:version] = '9.2.2'
697
+ resource = Resource.new(args)
698
+ expect(resource.version).to eq('9.2.2')
699
+ end
700
+ it 'can be set' do
701
+ new_version = '9.2.2'
702
+ resource = Resource.new(args)
703
+ resource.version = new_version
704
+ expect(resource.version).to eq(new_version)
705
+ end
706
+ it 'strips on initialization' do
707
+ args[:version] = '
708
+ 9.2.2
709
+ '
710
+ resource = Resource.new(args)
711
+ expect(resource.version).to eq('9.2.2')
712
+ end
713
+ it 'strips on set' do
714
+ resource = Resource.new(args)
715
+ resource.version = '
716
+ 9.2.2
717
+ '
718
+ expect(resource.version).to eq('9.2.2')
719
+ end
720
+ end
660
721
 
661
- describe 'language' do
662
- it 'returns the language'
663
- end
722
+ describe '#rights_list' do
723
+ it 'defaults to empty' do
724
+ resource = Resource.new(args)
725
+ expect(resource.rights_list).to eq([])
726
+ end
664
727
 
665
- describe 'language=' do
666
- it 'sets the languge'
667
- it 'requires a language'
668
- end
728
+ describe('rights_list:') do
729
+ it 'can be initialized' do
730
+ rights_list = [
731
+ Rights.new(value: 'CC0 1.0 Universal', uri: URI('http://creativecommons.org/publicdomain/zero/1.0/')),
732
+ Rights.new(value: 'This work is free of known copyright restrictions.', uri: URI('http://creativecommons.org/publicdomain/mark/1.0/'))
733
+ ]
734
+ args[:rights_list] = rights_list
735
+ resource = Resource.new(args)
736
+ expect(resource.rights_list).to eq(rights_list)
737
+ end
738
+ it 'can\'t be initialized to nil' do
739
+ args[:rights_list] = nil
740
+ resource = Resource.new(args)
741
+ expect(resource.rights_list).to eq([])
742
+ end
743
+ end
669
744
 
670
- describe 'resource_type' do
671
- it 'returns the resource type'
672
- end
745
+ describe '#rights_list=' do
746
+ it 'can be set' do
747
+ resource = Resource.new(args)
748
+ rights_list = [
749
+ Rights.new(value: 'CC0 1.0 Universal', uri: URI('http://creativecommons.org/publicdomain/zero/1.0/')),
750
+ Rights.new(value: 'This work is free of known copyright restrictions.', uri: URI('http://creativecommons.org/publicdomain/mark/1.0/'))
751
+ ]
752
+ resource.rights_list = rights_list
753
+ expect(resource.rights_list).to eq(rights_list)
754
+ end
673
755
 
674
- describe 'resource_type=' do
675
- it 'sets the resource type'
676
- it 'requires a resource type'
677
- end
756
+ it 'can\'t be set to nil' do
757
+ resource = Resource.new(args)
758
+ resource.rights_list = nil
759
+ expect(resource.rights_list).to eq([])
760
+ end
761
+ end
678
762
 
679
- describe 'alternate_identifiers' do
680
- it 'returns the alternate identifier list'
681
- it 'returns an editable list'
682
- end
763
+ end
683
764
 
684
- describe 'alternate_identifiers=' do
685
- it 'overwrites the alternate identifier list'
686
- it 'accepts an empty list'
687
- end
765
+ describe '#descriptions' do
766
+ it 'defaults to empty' do
767
+ resource = Resource.new(args)
768
+ expect(resource.descriptions).to eq([])
769
+ end
688
770
 
689
- describe 'related_identifiers' do
690
- it 'returns the related identifier list'
691
- it 'returns an editable list'
692
- end
771
+ describe 'descriptions:' do
772
+ it 'can be initialized' do
773
+ descriptions = [
774
+ Description.new(language: 'en-us', type: DescriptionType::ABSTRACT, value: 'Exterminate all the brutes!'),
775
+ Description.new(language: 'en-us', type: DescriptionType::METHODS, value: 'unsound')
776
+ ]
777
+ args[:descriptions] = descriptions
778
+ resource = Resource.new(args)
779
+ expect(resource.descriptions).to eq(descriptions)
780
+ end
781
+ it 'can\'t be initialized to nil' do
782
+ args[:descriptions] = nil
783
+ resource = Resource.new(args)
784
+ expect(resource.descriptions).to eq([])
785
+ end
693
786
 
694
- describe 'related_identifiers=' do
695
- it 'overwrites the related identifier list'
696
- it 'accepts an empty list'
697
- end
787
+ it 'ignores descriptions without values' do
788
+ descriptions = [
789
+ Description.allocate,
790
+ Description.new(language: 'en-us', type: DescriptionType::METHODS, value: 'unsound'),
791
+ Description.allocate
792
+ ]
793
+ args[:descriptions] = descriptions
794
+ resource = Resource.new(args)
795
+ expect(resource.descriptions).to eq([descriptions[1]])
796
+ end
797
+ end
698
798
 
699
- describe 'sizes' do
700
- it 'returns the size list'
701
- it 'returns an editable list'
702
- end
799
+ describe '#descriptions=' do
800
+ it 'can be set' do
801
+ descriptions = [
802
+ Description.new(language: 'en-us', type: DescriptionType::ABSTRACT, value: 'Exterminate all the brutes!'),
803
+ Description.new(language: 'en-us', type: DescriptionType::METHODS, value: 'unsound')
804
+ ]
805
+ resource = Resource.new(args)
806
+ resource.descriptions = descriptions
807
+ expect(resource.descriptions).to eq(descriptions)
808
+ end
809
+ it 'can\'t be set to nil' do
810
+ resource = Resource.new(args)
811
+ resource.descriptions = nil
812
+ expect(resource.descriptions).to eq([])
813
+ end
703
814
 
704
- describe 'sizes=' do
705
- it 'overwrites the size list'
706
- it 'accepts an empty list'
707
- end
815
+ it 'ignores descriptions without values' do
816
+ descriptions = [
817
+ Description.allocate,
818
+ Description.new(language: 'en-us', type: DescriptionType::METHODS, value: 'unsound'),
819
+ Description.allocate
820
+ ]
821
+ resource = Resource.new(args)
822
+ resource.descriptions = descriptions
823
+ expect(resource.descriptions).to eq([descriptions[1]])
824
+ end
825
+ end
826
+ end
708
827
 
709
- describe 'formats' do
710
- it 'returns the size list'
711
- it 'returns an editable list'
712
- end
828
+ describe '#geo_locations' do
829
+ it 'defaults to empty' do
830
+ resource = Resource.new(args)
831
+ expect(resource.geo_locations).to eq([])
832
+ end
713
833
 
714
- describe 'formats=' do
715
- it 'overwrites the size list'
716
- it 'accepts an empty list'
717
- end
834
+ describe 'geo_locations:' do
835
+ it 'can be initialized' do
836
+ geo_locations = [
837
+ GeoLocation.new(point: GeoLocationPoint.new(47.61, -122.33)),
838
+ GeoLocation.new(box: GeoLocationBox.new(-33.45, -122.33, 47.61, -70.67))
839
+ ]
840
+ args[:geo_locations] = geo_locations
841
+ resource = Resource.new(args)
842
+ expect(resource.geo_locations).to eq(geo_locations)
843
+ end
844
+ it 'can\'t be initialized to nil' do
845
+ args[:geo_locations] = nil
846
+ resource = Resource.new(args)
847
+ expect(resource.geo_locations).to eq([])
848
+ end
849
+ it 'ignores empty locations' do
850
+ geo_locations = [
851
+ GeoLocation.new,
852
+ GeoLocation.new(point: GeoLocationPoint.new(47.61, -122.33)),
853
+ GeoLocation.new
854
+ ]
855
+ args[:geo_locations] = geo_locations
856
+ resource = Resource.new(args)
857
+ expect(resource.geo_locations).to eq([geo_locations[1]])
858
+ end
859
+ end
718
860
 
719
- describe 'version' do
720
- it 'returns the version'
721
- end
861
+ describe '#geo_locations=' do
862
+ it 'can be set' do
863
+ resource = Resource.new(args)
864
+ geo_locations = [
865
+ GeoLocation.new(point: GeoLocationPoint.new(47.61, -122.33)),
866
+ GeoLocation.new(box: GeoLocationBox.new(-33.45, -122.33, 47.61, -70.67))
867
+ ]
868
+ resource.geo_locations = geo_locations
869
+ expect(resource.geo_locations).to eq(geo_locations)
870
+ end
871
+ it 'can\'t be set to nil' do
872
+ resource = Resource.new(args)
873
+ resource.geo_locations = nil
874
+ expect(resource.geo_locations).to eq([])
875
+ end
876
+ it 'ignores empty locations' do
877
+ resource = Resource.new(args)
878
+ geo_locations = [
879
+ GeoLocation.new,
880
+ GeoLocation.new(point: GeoLocationPoint.new(47.61, -122.33)),
881
+ GeoLocation.new
882
+ ]
883
+ resource.geo_locations = geo_locations
884
+ expect(resource.geo_locations).to eq([geo_locations[1]])
885
+ end
886
+ end
887
+ end
722
888
 
723
- describe 'version=' do
724
- it 'sets the languge'
725
- it 'accepts nil'
726
889
  end
727
890
 
728
- describe 'rights' do
729
- it 'returns the rights list'
730
- it 'returns an editable list'
731
- end
891
+ describe 'compatibility' do
732
892
 
733
- describe 'rights=' do
734
- it 'overwrites the rights list'
735
- it 'accepts an empty list'
736
- end
893
+ def xml_text_from(file, fix_dash1)
894
+ xml_text = File.read(file)
895
+ xml_text = fix_dash1(xml_text) if fix_dash1
896
+ xml_text
897
+ end
737
898
 
738
- describe 'descriptions' do
739
- it 'returns the description list'
740
- it 'returns an editable list'
741
- end
899
+ def parse_file(xml_text, basename)
900
+ return Resource.parse_xml(xml_text)
901
+ rescue Exception => e # rubocop:disable Lint/RescueException
902
+ warn "Error parsing #{basename}: #{e}"
903
+ File.open("tmp/#{basename}-xml_text.xml", 'w') { |t| t.write(xml_text) }
904
+ File.open("tmp/#{basename}-parse_error.xml", 'w') { |t| t.write(xml_text) }
905
+ raise
906
+ end
742
907
 
743
- describe 'descriptions=' do
744
- it 'overwrites the description list'
745
- it 'accepts an empty list'
746
- end
908
+ def write_xml(resource, basename, options)
909
+ # Workaround for Dash 1 datacite.xml with missing DOI
910
+ resource.identifier = Identifier.from_doi('10.5555/12345678') unless resource.identifier
911
+ return resource.write_xml(options)
912
+ rescue Exception => e # rubocop:disable Lint/RescueException
913
+ warn "Error writing #{basename}: #{e}"
914
+ raise
915
+ end
747
916
 
748
- describe 'geo_locations' do
749
- it 'returns the geolocation list'
750
- it 'returns an editable list'
751
- end
917
+ def normalize(xml_str)
918
+ xml_str
919
+ .gsub(%r{<([^>]+tude)>([0-9.-]+?)(0?)0+</\1>}, '<\\1>\\2\\3</\\1>') # strip trailing coordinate zeroes
920
+ .gsub(/ "([^"]+)"/, ' &quot;\\1&quot;') # entity-escape quotes in text
921
+ .gsub('&lt;br /&gt;', '<br/>') # entity-de-escape <br/> tags
922
+ .gsub('"', "'") # swap double for single quotes
923
+ .gsub(%r{<(geoLocation[^>]+)>[^<]+</\1>}) { |loc| loc.gsub(/([0-9\-]+\.[0-9]+?)0+([^0-9])/, '\\1\\2') } # strip trailing coordinate zeroes
924
+ end
752
925
 
753
- describe 'geo_locations=' do
754
- it 'overwrites the geolocation list'
755
- it 'accepts an empty list'
756
- end
926
+ def fix_dash1(xml_str)
927
+ # Workaround for Dash 1 datacite.xml with:
928
+ # - missing DOI
929
+ # - empty tags
930
+ # - nested contributors instead of contributorNames
931
+ xml_str
932
+ .gsub(%r{<[^>]+/>}, '') # remove empty tags
933
+ .gsub(%r{<([^>]+)>\s+</\1>}, '') # remove empty tag pairs
934
+ .gsub(%r{(<date[^>]*>)(\d{4})-(\d{4})(</date>)}, '\\1\\2/\\3\\4') # fix date ranges
935
+ .gsub(%r{(<contributor[^>/]+>\s*)<contributor>([^<]+)</contributor>(\s*</contributor>)}, '\\1<contributorName>\\2</contributorName>\\3') # fix broken contributors
936
+ end
757
937
 
758
- describe 'XML mapping' do
759
-
760
- describe '#parse_xml' do
761
- it 'handles all Dash 1 documents' do
762
- versions = []
763
-
764
- Dir.glob('spec/data/dash1-datacite-xml/*mrt-datacite.xml') do |f|
765
- basename = File.basename(f)
766
- bad_contrib_regex = Regexp.new('<contributor contributorType="([^"]+)">\p{Space}*<contributor>([^<]+)</contributor>\p{Space}*</contributor>', Regexp::MULTILINE)
767
- good_contrib_replacement = "<contributor contributorType=\"\\1\">\n<contributorName>\\2</contributorName>\n</contributor>"
768
- xml_text = File.read(f).gsub(bad_contrib_regex, good_contrib_replacement)
769
-
770
- resource = nil
771
- begin
772
- resource = Resource.parse_xml(xml_text, mapping: :nonvalidating)
773
- rescue Exception => e # rubocop:disable Lint/RescueException:
774
- puts "Error parsing #{basename}: #{e}"
775
- File.open("tmp/#{basename}-parse_error.xml", 'w') { |t| t.write(xml_text) }
776
- raise
777
- end
778
- next unless resource
938
+ def it_round_trips(file:, mapping: :_default, fix_dash1: false) # rubocop:disable Metrics/AbcSize
939
+ options = { mapping: mapping }
940
+ basename = File.basename(file)
941
+ xml_text = xml_text_from(file, fix_dash1)
942
+ resource = parse_file(xml_text, basename)
943
+ actual_xml = write_xml(resource, basename, options)
944
+ expected_xml = normalize(xml_text)
945
+ expected_xml.gsub!(/(<resource[^>]+>)\s+(<creators>)/, "\\1\n <identifier identifierType=\"DOI\">10.5555/12345678</identifier>\n \\2") if fix_dash1
946
+ begin
947
+ expect(actual_xml).to be_xml(expected_xml)
948
+ rescue Exception # rubocop:disable Lint/RescueException
949
+ File.open("tmp/#{basename}-expected.xml", 'w') { |t| t.write(expected_xml) }
950
+ File.open("tmp/#{basename}-actual.xml", 'w') { |t| t.write(actual_xml) }
951
+ raise
952
+ end
953
+ end
954
+
955
+ it 'reads all datacite 4 example documents' do
956
+ Dir.glob('spec/data/datacite4/datacite-example-*.xml') { |f| it_round_trips(file: f) }
957
+ end
958
+ it 'reads all datacite 3 example documents' do
959
+ Dir.glob('spec/data/datacite3/datacite-example-*.xml') { |f| it_round_trips(file: f, mapping: :datacite_3) }
960
+ end
961
+ it 'reads all dash 1 docs, with caveats' do
962
+ Dir.glob('spec/data/dash1/*.xml') { |f| it_round_trips(file: f, mapping: :datacite_3, fix_dash1: true) }
963
+ end
779
964
 
780
- versions << resource.version if resource.version
965
+ describe 'DC4 to DC3' do
781
966
 
782
- actual_xml = nil
783
- begin
784
- actual_xml = resource.write_xml
785
- rescue Exception => e # rubocop:disable Lint/RescueException:
786
- puts "Error writing #{basename}: #{e}"
787
- raise
788
- end
789
- next unless actual_xml
790
-
791
- actual_tidy = actual_xml
792
- .gsub('<dcs:language>en</dcs:language>', '')
793
- .gsub(" xml:lang='en'", '')
794
- .gsub('<language>en</language>', '')
795
- expected_tidy = xml_text
796
- .gsub('<br/>', '[BREAK]')
797
- .gsub(Regexp.new('<[a-zA-Z]+/>'), '')
798
- .gsub('[BREAK]', '<br/>')
799
- .gsub(Regexp.new('<subjects>\p{space}</subjects>', Regexp::MULTILINE), '')
800
- .gsub("'", '&apos;')
801
- .gsub('"', "'")
802
- .gsub("<subject schemeURI='http://www.nlm.nih.gov/mesh/' subjectScheme='MeSH'/>", '')
803
-
804
- begin
805
- expect(actual_tidy).to be_xml(expected_tidy)
806
- rescue Exception # rubocop:disable Lint/RescueException:
807
- File.open("tmp/#{basename}-original.xml", 'w') { |t| t.write(expected_tidy) }
808
- File.open("tmp/#{basename}-roundtrip.xml", 'w') { |t| t.write(actual_tidy) }
809
- raise
810
- end
967
+ attr_reader :resource
968
+ attr_reader :rexml
969
+ attr_reader :warnings
970
+
971
+ def warnings_including(substring)
972
+ warnings.select { |w| w.include?(substring) }
973
+ end
974
+
975
+ def expect_warning(substring, count, include_matches = false)
976
+ matches = warnings_including(substring)
977
+ found_count = matches.size
978
+ msg = "expected #{count} warnings including '#{substring}', found #{found_count}"
979
+ msg << ": #{matches}" if include_matches
980
+ expect(found_count).to eq(count), msg
981
+ end
982
+
983
+ def expect_matches(xpath, count, include_matches = false)
984
+ matches = REXML::XPath.match(rexml, xpath)
985
+ found_count = matches.size
986
+ msg = "expected #{count} matches for XPath '#{xpath}', found #{found_count}"
987
+ msg << ": #{matches}" if include_matches
988
+ expect(found_count).to eq(count), msg
989
+ end
990
+
991
+ before(:each) do
992
+ @warnings = []
993
+ allow(ReadOnlyNodes).to receive(:warn) do |w|
994
+ warnings << w
995
+ Kernel.warn(w) # for debugging
996
+ end
997
+
998
+ xml = File.read('spec/data/datacite-4-synthetic.xml')
999
+ @resource = Resource.parse_xml(xml)
1000
+ @rexml = resource.save_to_xml(mapping: :datacite_3)
1001
+ end
1002
+
1003
+ it 'sets the kernel-3 namespace' do
1004
+ expect(rexml.namespace).to eq(DATACITE_3_NAMESPACE.uri)
1005
+ end
1006
+
1007
+ it 'warns about givenNames and familyNames' do
1008
+ name_tags = %w(givenName familyName)
1009
+ name_tags.each do |tag|
1010
+ expect_matches("//#{tag}", 0, true)
1011
+ expect_warning(tag, 1)
811
1012
  end
812
1013
  end
1014
+
1015
+ it 'warns about FundingReferences' do
1016
+ expect_matches('//fundingReferences', 0, true)
1017
+ expect_warning('fundingReferences', 1)
1018
+ end
1019
+
1020
+ it 'warns about IGSN identifiers' do
1021
+ expect_warning('IGSN', 1)
1022
+ end
1023
+
1024
+ it 'warns about geoLocationPolygons' do
1025
+ expect_warning('geoLocationPolygon', 1)
1026
+ end
1027
+
813
1028
  end
814
1029
 
815
- describe '#save_to_xml' do
816
- it 'writes XML' do
817
- resource = Resource.new(
818
- identifier: Identifier.new(value: '10.5072/D3P26Q35R-Test'),
819
- creators: [
820
- Creator.new(name: 'Fosmire, Michael'),
821
- Creator.new(name: 'Wertz, Ruth'),
822
- Creator.new(name: 'Purzer, Senay')
823
- ],
824
- titles: [
825
- Title.new(value: 'Critical Engineering Literacy Test (CELT)')
826
- ],
827
- publisher: 'Purdue University Research Repository (PURR)',
828
- publication_year: 2013,
829
- subjects: [
830
- Subject.new(value: 'Assessment'),
831
- Subject.new(value: 'Information Literacy'),
832
- Subject.new(value: 'Engineering'),
833
- Subject.new(value: 'Undergraduate Students'),
834
- Subject.new(value: 'CELT'),
835
- Subject.new(value: 'Purdue University')
836
- ],
837
- language: 'en',
838
- resource_type: ResourceType.new(resource_type_general: ResourceTypeGeneral::DATASET, value: 'Dataset'),
839
- version: '1',
840
- descriptions: [
841
- Description.new(
842
- type: DescriptionType::ABSTRACT,
843
- value: 'We developed an instrument, Critical Engineering Literacy Test (CELT), which is a multiple choice instrument
844
- designed to measure undergraduate students’ scientific and information literacy skills. It requires students to
845
- first read a technical memo and, based on the memo’s arguments, answer eight multiple choice and six open-ended
846
- response questions. We collected data from 143 first-year engineering students and conducted an item analysis. The
847
- KR-20 reliability of the instrument was .39. Item difficulties ranged between .17 to .83. The results indicate low
848
- reliability index but acceptable levels of item difficulties and item discrimination indices. Students were most
849
- challenged when answering items measuring scientific and mathematical literacy (i.e., identifying incorrect
850
- information).'
851
- )
852
- ]
853
- )
1030
+ describe 'DC3 to DC4' do
1031
+ attr_reader :resource
1032
+ attr_reader :rexml
854
1033
 
855
- expected_xml = '<resource xsi:schemaLocation=\'http://datacite.org/schema/kernel-3 http://schema.datacite.org/meta/kernel-3/metadata.xsd\' xmlns=\'http://datacite.org/schema/kernel-3\' xmlns:xsi=\'http://www.w3.org/2001/XMLSchema-instance\'>
856
- <identifier identifierType=\'DOI\'>10.5072/D3P26Q35R-Test</identifier>
857
- <creators>
858
- <creator>
859
- <creatorName>Fosmire, Michael</creatorName>
860
- </creator>
861
- <creator>
862
- <creatorName>Wertz, Ruth</creatorName>
863
- </creator>
864
- <creator>
865
- <creatorName>Purzer, Senay</creatorName>
866
- </creator>
867
- </creators>
868
- <titles>
869
- <title xml:lang=\'en\'>Critical Engineering Literacy Test (CELT)</title>
870
- </titles>
871
- <publisher>Purdue University Research Repository (PURR)</publisher>
872
- <publicationYear>2013</publicationYear>
873
- <subjects>
874
- <subject xml:lang=\'en\'>Assessment</subject>
875
- <subject xml:lang=\'en\'>Information Literacy</subject>
876
- <subject xml:lang=\'en\'>Engineering</subject>
877
- <subject xml:lang=\'en\'>Undergraduate Students</subject>
878
- <subject xml:lang=\'en\'>CELT</subject>
879
- <subject xml:lang=\'en\'>Purdue University</subject>
880
- </subjects>
881
- <language>en</language>
882
- <resourceType resourceTypeGeneral=\'Dataset\'>Dataset</resourceType>
883
- <version>1</version>
884
- <descriptions>
885
- <description descriptionType=\'Abstract\' xml:lang=\'en\'>We developed an instrument, Critical Engineering Literacy Test (CELT), which is a multiple choice instrument designed to measure undergraduate students’ scientific and information literacy skills. It requires students to first read a technical memo and, based on the memo’s arguments, answer eight multiple choice and six open-ended response questions. We collected data from 143 first-year engineering students and conducted an item analysis. The KR-20 reliability of the instrument was .39. Item difficulties ranged between .17 to .83. The results indicate low reliability index but acceptable levels of item difficulties and item discrimination indices. Students were most challenged when answering items measuring scientific and mathematical literacy (i.e., identifying incorrect information).</description>
886
- </descriptions>
887
- </resource>'
888
-
889
- actual_xml = resource.write_xml
890
- begin
891
- expect(actual_xml).to be_xml(expected_xml)
892
- rescue Exception # rubocop:disable Lint/RescueException:
893
- File.open('tmp/expected.xml', 'w') { |t| t.write(expected_xml) }
894
- File.open('tmp/actual.xml', 'w') { |t| t.write(actual_xml) }
895
- raise
896
- end
897
- end
898
- end
899
-
900
- it 'round-trips' do
901
- xml_text = File.read('spec/data/resource.xml')
902
- resource = Resource.parse_xml(xml_text)
903
- expect(resource.save_to_xml).to be_xml(xml_text)
1034
+ before(:each) do
1035
+ @resource = Resource.load_from_file('spec/data/datacite3/datacite-example-full-v3.1.xml')
1036
+ @rexml = resource.save_to_xml
1037
+ end
1038
+
1039
+ it 'writes a DC3 document as DC4' do
1040
+ expect(rexml.namespace).to eq(DATACITE_4_NAMESPACE.uri)
1041
+ end
904
1042
  end
1043
+ end
905
1044
 
906
- it 'allows a namespace prefix' do
907
- resource = Resource.new(
908
- identifier: @id,
909
- creators: @creators,
910
- titles: @titles,
911
- publisher: @publisher,
912
- publication_year: @pub_year
913
- )
914
- Resource.namespace_prefix = 'dcs'
915
- expect(Resource.namespace.prefix).to eq('dcs')
1045
+ describe '#namespace_prefix=' do
916
1046
 
917
- expected = '<dcs:resource xmlns:dcs="http://datacite.org/schema/kernel-3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://datacite.org/schema/kernel-3 http://schema.datacite.org/meta/kernel-3/metadata.xsd">
1047
+ attr_reader :dcs3_xml
1048
+ attr_reader :dcs4_xml
1049
+
1050
+ before(:each) do
1051
+ @dcs3_xml = '<dcs:resource xmlns:dcs="http://datacite.org/schema/kernel-3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://datacite.org/schema/kernel-3 http://schema.datacite.org/meta/kernel-3/metadata.xsd">
918
1052
  <dcs:identifier identifierType="DOI">10.14749/1407399495</dcs:identifier>
919
1053
  <dcs:creators>
920
1054
  <dcs:creator>
@@ -938,61 +1072,47 @@ module Datacite
938
1072
  <dcs:publicationYear>2015</dcs:publicationYear>
939
1073
  <dcs:language>en</dcs:language>
940
1074
  </dcs:resource>'
941
-
942
- expect(resource.save_to_xml).to be_xml(expected)
943
- end
944
- end
945
-
946
- describe 'convenience accessors' do
947
-
948
- before :each do
949
- xml_text = File.read('spec/data/resource.xml')
950
- @resource = Resource.parse_xml(xml_text)
951
-
952
- @funder = Contributor.new(
953
- name: 'The Ministry of Magic',
954
- identifier: NameIdentifier.new(
955
- scheme: 'IATI',
956
- scheme_uri: URI('http://iatistandard.org/201/codelists/OrganisationIdentifier/'),
957
- value: 'GR-9¾'
958
- ),
959
- type: ContributorType::FUNDER)
960
- @resource.contributors << @funder
1075
+ @dcs4_xml = dcs3_xml.gsub('kernel-3', 'kernel-4')
961
1076
  end
962
1077
 
963
- describe 'creator_names' do
964
- it 'extracts the creator names' do
965
- expect(@resource.creator_names).to eq(['Miller, Elizabeth'])
966
- end
1078
+ it 'reads DC3 with namespace prefix' do
1079
+ resource = Resource.parse_xml(dcs3_xml)
1080
+ expect(resource.save_to_xml(mapping: :datacite_3)).to be_xml(dcs3_xml)
967
1081
  end
968
1082
 
969
- describe 'creator_affiliations' do
970
- it 'extracts the creator affiliations' do
971
- expect(@resource.creator_affiliations).to eq([['DataCite']])
972
- end
1083
+ it 'writes DC3 with namespace prefix' do
1084
+ resource = Resource.parse_xml(dcs3_xml)
1085
+ resource.namespace_prefix = 'dcs'
1086
+ xml = resource.write_xml(mapping: :datacite_3)
1087
+ expect(xml).not_to match(%r{<[a-z "=/]+>})
1088
+ expect(xml).to match(%r{<dcs:[a-z "=/]+>})
973
1089
  end
974
1090
 
975
- describe 'funder_contrib' do
976
- it 'extracts the funder contrib' do
977
- expect(@resource.funder_contrib).to eq(@funder)
978
- end
1091
+ it 'reads DC4 with namespace prefix' do
1092
+ resource = Resource.parse_xml(dcs4_xml)
1093
+ expect(resource.save_to_xml).to be_xml(dcs4_xml)
979
1094
  end
980
1095
 
981
- describe 'funder_name' do
982
- it 'extracts the funder name' do
983
- expect(@resource.funder_name).to eq(@funder.name)
984
- end
1096
+ it 'writes DC4 with namespace prefix' do
1097
+ resource = Resource.parse_xml(dcs4_xml)
1098
+ resource.namespace_prefix = 'dcs'
1099
+ xml = resource.write_xml
1100
+ expect(xml).not_to match(%r{<[a-z "=/]+>})
1101
+ expect(xml).to match(%r{<dcs:[a-z "=/]+>})
985
1102
  end
986
1103
 
987
- describe 'funder_id' do
988
- it 'extracts the funder id' do
989
- expect(@resource.funder_id).to eq(@funder.identifier)
990
- end
991
- end
1104
+ end
992
1105
 
993
- describe 'funder_id_value' do
994
- it 'extracts the funder id value' do
995
- expect(@resource.funder_id_value).to eq(@funder.identifier.value)
1106
+ describe '#save_to_file' do
1107
+ it 'saves to a file' do
1108
+ xml_text = File.read('spec/data/datacite4/datacite-example-full-v4.0.xml')
1109
+ resource = Resource.parse_xml(xml_text)
1110
+ Dir.mktmpdir('resource_spec') do |dir|
1111
+ path = "#{dir}/resource.xml"
1112
+ resource.save_to_file(path)
1113
+ actual = File.read(path)
1114
+ expected = xml_text.gsub('41.090', '41.09')
1115
+ expect(actual).to be_xml(expected)
996
1116
  end
997
1117
  end
998
1118
  end