<commit_before>package org.ambraproject.rhino.rest.controller;

import com.google.gson.Gson;
import org.ambraproject.rhino.identity.Doi;
import org.ambraproject.rhino.rest.DoiEscaping;
import org.ambraproject.rhino.service.ArticleCrudService;
import org.ambraproject.rhino.service.CommentCrudService;
import org.ambraproject.rhino.service.IssueCrudService;
import org.ambraproject.rhino.service.VolumeCrudService;
import org.ambraproject.rhino.util.response.Transceiver;
import org.ambraproject.rhino.view.ResolvedDoiView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Calendar;
import java.util.Optional;

@Controller
public class ArticleItemReadController extends RestController {

  @Autowired
  private ArticleCrudService articleCrudService;
  @Autowired
  private VolumeCrudService volumeCrudService;
  @Autowired
  private IssueCrudService issueCrudService;
  @Autowired
  private CommentCrudService commentCrudService;
  @Autowired
  private Gson entityGson;

  @Transactional(readOnly = true)
  @RequestMapping(value = "/dois/{doi:.+}", method = RequestMethod.GET)
  public void resolve(HttpServletRequest request, HttpServletResponse response,
                      @PathVariable("doi") String escapedDoi)
      throws IOException {
    Doi doi = DoiEscaping.unescape(escapedDoi);

    // Look for the DOI in the corpus of articles
    Optional<ResolvedDoiView> itemOverview = articleCrudService.getItemOverview(doi);
    if (itemOverview.isPresent()) {
      asTransceiver(itemOverview.get()).respond(request, response, entityGson);
      return;
    }

    // TODO: It may belong to another data type
  }

  private Transceiver asTransceiver(ResolvedDoiView view) {
    return new Transceiver() {
      @Override
      protected Object getData() throws IOException {
        return view;
      }

      @Override
      protected Calendar getLastModifiedDate() throws IOException {
        return null;
      }
    };
  }

}<commit_msg>DPRO-2730: Implement DOI searches on non-article objects<commit_after>package org.ambraproject.rhino.rest.controller;

import com.google.gson.Gson;
import org.ambraproject.rhino.identity.CommentIdentifier;
import org.ambraproject.rhino.identity.Doi;
import org.ambraproject.rhino.identity.IssueIdentifier;
import org.ambraproject.rhino.identity.VolumeIdentifier;
import org.ambraproject.rhino.rest.DoiEscaping;
import org.ambraproject.rhino.rest.RestClientException;
import org.ambraproject.rhino.service.ArticleCrudService;
import org.ambraproject.rhino.service.CommentCrudService;
import org.ambraproject.rhino.service.IssueCrudService;
import org.ambraproject.rhino.service.VolumeCrudService;
import org.ambraproject.rhino.util.response.Transceiver;
import org.ambraproject.rhino.view.ResolvedDoiView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Calendar;
import java.util.EnumSet;
import java.util.Optional;

@Controller
public class ArticleItemReadController extends RestController {

  @Autowired
  private ArticleCrudService articleCrudService;
  @Autowired
  private VolumeCrudService volumeCrudService;
  @Autowired
  private IssueCrudService issueCrudService;
  @Autowired
  private CommentCrudService commentCrudService;
  @Autowired
  private Gson entityGson;

  @Transactional(readOnly = true)
  @RequestMapping(value = "/dois/{doi:.+}", method = RequestMethod.GET)
  public void resolve(HttpServletRequest request, HttpServletResponse response,
                      @PathVariable("doi") String escapedDoi)
      throws IOException {
    Doi doi = DoiEscaping.unescape(escapedDoi);
    asTransceiver(findDoiTarget(doi)).respond(request, response, entityGson);
  }

  private Transceiver asTransceiver(ResolvedDoiView view) {
    return new Transceiver() {
      @Override
      protected Object getData() throws IOException {
        return view;
      }

      @Override
      protected Calendar getLastModifiedDate() throws IOException {
        return null;
      }
    };
  }

  private ResolvedDoiView findDoiTarget(Doi doi) throws IOException {
    // Look for the DOI in the corpus of articles
    Optional<ResolvedDoiView> itemOverview = articleCrudService.getItemOverview(doi);
    if (itemOverview.isPresent()) {
      return itemOverview.get();
    }

    // Not found as an Article or ArticleItem. Check other object types that use DOIs.
    return EnumSet.allOf(DoiLookup.class).stream()
        .filter(lookup -> lookup.exists(this, doi))
        .findAny()
        .map(matchedLookup -> ResolvedDoiView.create(matchedLookup.getType()))
        .orElseThrow(() -> new RestClientException("DOI not found: " + doi.getName(), HttpStatus.NOT_FOUND));
  }

  private static enum DoiLookup {
    VOLUME(ResolvedDoiView.DoiWorkType.VOLUME) {
      @Override
      public boolean exists(ArticleItemReadController controller, Doi doi) {
        return controller.volumeCrudService.getVolume(VolumeIdentifier.create(doi)).isPresent();
      }
    },
    ISSUE(ResolvedDoiView.DoiWorkType.ISSUE) {
      @Override
      public boolean exists(ArticleItemReadController controller, Doi doi) {
        return controller.issueCrudService.getIssue(IssueIdentifier.create(doi)).isPresent();
      }
    },
    COMMENT(ResolvedDoiView.DoiWorkType.COMMENT) {
      @Override
      public boolean exists(ArticleItemReadController controller, Doi doi) {
        return controller.commentCrudService.getComment(CommentIdentifier.create(doi)).isPresent();
      }
    };

    private final ResolvedDoiView.DoiWorkType type;

    private DoiLookup(ResolvedDoiView.DoiWorkType type) {
      this.type = type;
    }

    public ResolvedDoiView.DoiWorkType getType() {
      return type;
    }

    public abstract boolean exists(ArticleItemReadController controller, Doi doi);
  }

}
{'fraction_non_alphanumeric': 0.08787924077118517, 'fraction_numerical': 0.0005978179644298311, 'mean_word_length': 4.553526970954357, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2019545', 'n_tokens_mistral': 1954, 'n_tokens_neox': 1887, 'n_words': 375}