I've written the following code, I tried to condense the code by writing a lambda using the .ifPresentOrElse()
method of the Optional class, but I am not quite sure how to write my logic within the method. I am relatively new to streams, lambdas, and Java.
/*Scheduled Job creates a question record for each external Id present within
* our view, if user clicks on their experiment and scheduled job has not run yet
* then they will receive a whitelabel page
* What should happen:
* if user attempts to view their experiment details and question record doesn't exist yet
* a record of questions should be created upon API visit
*/
//if question is already mapped to external id, return the question details
Question questionObject;
Optional<Question> questionOpt = questionRepository.findByExternalId(externalId);
if (questionOpt.isPresent()) {
questionObject = questionOpt.get();
}
else {
//if not, make sure external id exists in view
Optional<SignalsExperimentCSView> expOpt = signalsExperimentCSViewRepository.findOneByExternalId(externalId);
//call to check if record in view contains this external id
if (expOpt.isPresent()) {
// if present within the view create a record
Question question = new Question();
question.setExternalId(externalId);
questionRepository.save(question);
questionObject = question;
} else {
//if the above doesn't exist in view then return an experiment not found page
//throw exception
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
Is it possible to write a lambda using the method .ifPresentOrElse()
with my current logic?
EDIT I will post the whole class as the logic pertaining to the function might make more sense:
package com.pdb.testdbconn.service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import com.pdb.testdbconn.dto.ExperimentDataDto;
import com.pdb.testdbconn.dto.ExperimentDataDto.Compound;
import com.pdb.testdbconn.dto.ExperimentDetails;
import com.pdb.testdbconn.models.Question;
import com.pdb.testdbconn.repositories.ExperimentDetailsRepository;
import com.pdb.testdbconn.repositories.QuestionRepository;
import com.pdb.testdbconn.repositories.SignalsExperimentCSViewRepository;
@Service
public class ExperimentDetailsService {
private static Logger logger = LoggerFactory.getLogger(ExperimentDetailsService.class);
private ExperimentDetailsRepository experimentDetailsRepository;
private QuestionRepository questionRepository;
private SignalsExperimentCSViewRepository signalsExperimentCSViewRepository;
public ExperimentDetailsService(ExperimentDetailsRepository experimentDetailsRepository,
QuestionRepository questionRepository,
SignalsExperimentCSViewRepository signalsExperimentCSViewRepository) {
this.experimentDetailsRepository = experimentDetailsRepository;
this.questionRepository = questionRepository;
this.signalsExperimentCSViewRepository = signalsExperimentCSViewRepository;
}
public ResponseEntity<Object> getExperimentDetails(String externalId) {
//custom query run within the repository
List<ExperimentDetails> experimentDetails = experimentDetailsRepository.findByExternalId(externalId);
//used for the custom response object
Map<String, Object> responseObj = new HashMap<>();
//create individual products from Experiment and map them into their own ds
List<ExperimentDataDto.Compound> productDetails = experimentDetails.stream()
.map(experiment ->
{
//instantiate compounds to add as a list to each experiment record
Compound compound = new ExperimentDataDto.Compound();
compound.setName(experiment.getName());
compound.setControlledStatus(experiment.getControlledStatus());
compound.setJurisdictionName(experiment.getJurisdictionName());
compound.setResultComments(experiment.getResultComments());
compound.setCodeName(experiment.getCodeName());
compound.setCorporateId(experiment.getCorporateId());
return compound;
}).distinct().collect(Collectors.toList());
logger.info("products: {}", productDetails);
// Question question = questionRepository.findByExternalId(externalId).orElseThrow(null);
/*Scheduled Job creates a question record for each external Id present within
* our view, if user clicks on their experiment and scheduled job has not run yet
* then will have whitelabel page
* What should happen:
* if user attempts to view their experiment details and question record doesn't exist yet
* a record of questions should be created upon API visit
*/
//if question is already mapped to external id, return the question details
// Question questionObject;
// Optional<Question> questionOpt = questionRepository.findByExternalId(externalId);
// if (questionOpt.isPresent()) {
// questionObject = questionOpt.get();
// }
// else {
// //if not make sure external id exists in view
// Optional<SignalsExperimentCSView> expOpt = signalsExperimentCSViewRepository.findOneByExternalId(externalId);
// //call to check if record in view contains this external id
// if (expOpt.isPresent()) {
// // if present within the view create a record
// Question question = new Question();
// question.setExternalId(externalId);
// questionRepository.save(question);
// questionObject = question;
// } else {
// //if the above doesn't exist in view then return an experiment not found page
// //throw exception
// return new ResponseEntity<>(HttpStatus.NOT_FOUND);
// }
// }
//trying to refactor to logic above
Question questionObject = questionRepository.findByExternalId(externalId)
.or(() ->
signalsExperimentCSViewRepository.findOneByExternalId(externalId)
.map(view -> {
Question question = new Question();
question.setExternalId(externalId);
questionRepository.save(question);
//I assume returning question is equivalent of setting quesitonObject
//to question
return question;
})
//wouldn't need .map(question -> ResponseEntity<>(question, HttpStatus.SUCCESS)) since logic is below
//in my response object
//receiving error on next line <> error on token
).orElseThrow(ResponseEntity<>(HttpStatus.NOT_FOUND));
logger.info("question: {}", questionObject);
responseObj.put("externalID", experimentDetails.get(0).getExternalId());
responseObj.put("isid", experimentDetails.get(0).getIsid());
responseObj.put("products", productDetails);
responseObj.put("question", questionObject);
//add questions key/value
return new ResponseEntity<>(responseObj, HttpStatus.OK);
}
}
You rather need the Optional.or method:
return questionRepository.findByExternalId(externalId)
.or(() ->
signalsExperimentCSViewRepository.findOneByExternalId(externalId)
.map(view -> {
Question question = new Question();
question.setExternalId(externalId);
questionRepository.save(question);
return question;
})
)
.map(question -> /* Map question to the ResponseEntity */)
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
or
Question questionObject = questionRepository.findByExternalId(externalId)
.or(() ->
signalsExperimentCSViewRepository.findOneByExternalId(externalId)
.map(view -> {
Question question = new Question();
question.setExternalId(externalId);
questionRepository.save(question);
return question;
})
)
.orElseThrow(() -> new HttpClientErrorException(HttpStatus.NOT_FOUND));
/* Map questionObject to the ResponseEntity */