DOIService.java

1
package edu.ucsb.cs.citelines.services;
2
3
import java.util.regex.Matcher;
4
import java.util.regex.Pattern;
5
import org.springframework.stereotype.Service;
6
7
/**
8
 * Recognizes a DOI (Digital Object Identifier) expressed in any of several common formats and
9
 * normalizes it to its canonical bare form (ANSI/NISO Z39.84), e.g. {@code
10
 * 10.1038/s41586-020-2649-2}.
11
 *
12
 * <p>Recognized formats include:
13
 *
14
 * <ul>
15
 *   <li>Actionable web URLs, e.g. {@code https://doi.org/10.1038/s41586-020-2649-2} or the
16
 *       deprecated {@code http://dx.doi.org/10.1038/s41586-020-2649-2}
17
 *   <li>shortDOI URLs, e.g. {@code https://doi.org/c234} or {@code https://doi.org/10/c234}
18
 *   <li>Plain/bare DOI strings, e.g. {@code 10.1038/s41586-020-2649-2}
19
 *   <li>The {@code doi:} prefix, e.g. {@code doi:10.1038/s41586-020-2649-2}
20
 *   <li>The {@code urn:doi:} namespace, e.g. {@code urn:doi:10.1038/s41586-020-2649-2}
21
 *   <li>The (deprecated) {@code info:doi/} URI scheme, e.g. {@code
22
 *       info:doi/10.1038/s41586-020-2649-2}
23
 * </ul>
24
 */
25
@Service
26
public class DOIService {
27
28
  // Matches a bare/canonical DOI, wherever it appears within a larger string (e.g. embedded in a
29
  // URL, an HTML anchor, or a doi:/urn:doi:/info:doi/ prefixed identifier).
30
  private static final Pattern DOI_PATTERN =
31
      Pattern.compile("\\b10\\.\\d{4,}(?:\\.\\d+)*/[^\\s<>\"]+", Pattern.CASE_INSENSITIVE);
32
33
  // Matches a shortDOI, either as a bare "10/xxxx" identifier or as a doi.org URL, with or
34
  // without the leading "10/" segment (e.g. "10/c234", "https://doi.org/c234", or
35
  // "https://doi.org/10/c234").
36
  private static final Pattern SHORT_DOI_PATTERN =
37
      Pattern.compile(
38
          "^(?:https?://(?:dx\\.)?doi\\.org/(?:10/)?|10/)([a-zA-Z0-9]+)$",
39
          Pattern.CASE_INSENSITIVE);
40
41
  /**
42
   * Normalizes a DOI given in any of the recognized formats to its canonical bare form.
43
   *
44
   * @param rawDoi the DOI, in any recognized format
45
   * @return the canonical, lower-cased, bare DOI (e.g. {@code 10.1038/s41586-020-2649-2})
46
   * @throws IllegalArgumentException if {@code rawDoi} cannot be recognized as a DOI in any of the
47
   *     supported formats
48
   */
49
  public String normalizeRawDOI(String rawDoi) {
50 1 1. normalizeRawDOI : negated conditional → KILLED
    if (rawDoi != null) {
51
      String trimmed = rawDoi.trim();
52
53
      Matcher shortDoiMatcher = SHORT_DOI_PATTERN.matcher(trimmed);
54 1 1. normalizeRawDOI : negated conditional → KILLED
      if (shortDoiMatcher.matches()) {
55 1 1. normalizeRawDOI : replaced return value with "" for edu/ucsb/cs/citelines/services/DOIService::normalizeRawDOI → KILLED
        return "10/" + shortDoiMatcher.group(1).toLowerCase();
56
      }
57
58
      Matcher doiMatcher = DOI_PATTERN.matcher(trimmed);
59 1 1. normalizeRawDOI : negated conditional → KILLED
      if (doiMatcher.find()) {
60 1 1. normalizeRawDOI : replaced return value with "" for edu/ucsb/cs/citelines/services/DOIService::normalizeRawDOI → KILLED
        return doiMatcher.group().toLowerCase();
61
      }
62
    }
63
64
    throw new IllegalArgumentException("Argument cannot be recognized as a DOI: " + rawDoi);
65
  }
66
}

Mutations

50

1.1
Location : normalizeRawDOI
Killed by : edu.ucsb.cs.citelines.services.DOIServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.citelines.services.DOIServiceTests]/[method:a_shortdoi_url_with_10_prefix_is_normalized()]
negated conditional → KILLED

54

1.1
Location : normalizeRawDOI
Killed by : edu.ucsb.cs.citelines.services.DOIServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.citelines.services.DOIServiceTests]/[method:a_shortdoi_url_with_10_prefix_is_normalized()]
negated conditional → KILLED

55

1.1
Location : normalizeRawDOI
Killed by : edu.ucsb.cs.citelines.services.DOIServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.citelines.services.DOIServiceTests]/[method:a_bare_shortdoi_is_normalized()]
replaced return value with "" for edu/ucsb/cs/citelines/services/DOIService::normalizeRawDOI → KILLED

59

1.1
Location : normalizeRawDOI
Killed by : edu.ucsb.cs.citelines.services.DOIServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.citelines.services.DOIServiceTests]/[method:a_bare_doi_is_returned_unchanged()]
negated conditional → KILLED

60

1.1
Location : normalizeRawDOI
Killed by : edu.ucsb.cs.citelines.services.DOIServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.citelines.services.DOIServiceTests]/[method:a_bare_doi_is_returned_unchanged()]
replaced return value with "" for edu/ucsb/cs/citelines/services/DOIService::normalizeRawDOI → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0