package com.syzton.sunread.service.exam; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javassist.NotFoundException; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.syzton.sunread.dto.exam.ObjectQuestionUpdateDTO; import com.syzton.sunread.model.book.Book; import com.syzton.sunread.model.exam.CapacityQuestion; import com.syzton.sunread.model.exam.ObjectiveQuestion; import com.syzton.sunread.model.exam.ObjectiveQuestion.QuestionType; import com.syzton.sunread.model.exam.Option; import com.syzton.sunread.model.exam.SpeedQuestion; import com.syzton.sunread.repository.book.BookRepository; import com.syzton.sunread.repository.exam.CapacityQuestionRepository; import com.syzton.sunread.repository.exam.ObjectiveQuestionRepository; import com.syzton.sunread.repository.exam.OptionRepository; import com.syzton.sunread.repository.exam.SpeedQuestionRepository; import com.syzton.sunread.util.ExcelUtil; @Service public class ObjectiveQuestionRepositoryService implements ObjectiveQuestionService { private static final Logger LOGGER = LoggerFactory .getLogger(ObjectiveQuestionRepositoryService.class); private ObjectiveQuestionRepository repository; private OptionRepository optionRepository; private CapacityQuestionRepository capacityRepository; private SpeedQuestionRepository speedRepository; private BookRepository bookRepository; @Autowired public ObjectiveQuestionRepositoryService( ObjectiveQuestionRepository repository,OptionRepository optionRepository, CapacityQuestionRepository capacityRepository,SpeedQuestionRepository speedRepository, BookRepository bookRepository) { this.repository = repository; this.optionRepository = optionRepository; this.capacityRepository = capacityRepository; this.speedRepository = speedRepository; this.bookRepository = bookRepository; } @Transactional(rollbackFor = { NotFoundException.class }) @Override public Page<ObjectiveQuestion> findAll(Pageable pageable) throws NotFoundException { Page<ObjectiveQuestion> objectiveQsPages = repository.findAll(pageable); return objectiveQsPages; } @Transactional @Override public ObjectiveQuestion add(ObjectiveQuestion added) { LOGGER.debug("Adding a new Objective question entry with information: {}", added); Long bookId = added.getBookId(); Book book = null; if(added.getObjectiveType().equals(QuestionType.VERIFY)){ book = bookRepository.findOne(bookId); book.getExtra().setHasVerifyTest(true); bookRepository.save(book); }else if(added.getObjectiveType().equals(QuestionType.WORD)){ book = bookRepository.findOne(bookId); book.getExtra().setHasWordTest(true); bookRepository.save(book); } return repository.save(added); } @Override public ObjectiveQuestion deleteById(Long id) throws NotFoundException { LOGGER.debug("Deleting a to-do entry with id: {}", id); ObjectiveQuestion deleted = findById(id); LOGGER.debug("Deleting to-do entry: {}", deleted); repository.delete(deleted); return deleted; } @Transactional(readOnly = true, rollbackFor = { NotFoundException.class }) @Override public ObjectiveQuestion findById(Long id) throws NotFoundException { LOGGER.debug("Finding a to-do entry with id: {}", id); ObjectiveQuestion found = repository.findOne(id); LOGGER.debug("Found to-do entry: {}", found); if (found == null) { throw new NotFoundException("No to-entry found with id: " + id); } return found; } @Transactional(rollbackFor = { NotFoundException.class }) @Override public ObjectiveQuestion update(ObjectQuestionUpdateDTO updated) throws NotFoundException { LOGGER.debug("Updating contact with information: {}", updated); ObjectiveQuestion model = findById(updated.getId()); LOGGER.debug("Found a to-do entry: {}", model); if(updated.getCorrectAnswer().getId()==null){ throw new NotFoundException("correct Answer not found"); } Option correct = optionRepository.findOne(updated.getCorrectAnswer().getId()); if(correct==null){ throw new NotFoundException("correct Answer not found"); } model.setCorrectAnswer(correct); model.setObjectiveType(updated.getObjectiveType()); List<Option> list = updated.getOptions(); List<Option> options = new ArrayList<Option>(); for(int i=0;i<list.size();i++){ Long id = list.get(i).getId(); Option option = optionRepository.findOne(id); if(id == null){ Option newOption = list.get(i); option = optionRepository.save(newOption); } if(option == null){ continue; } option.setTag(list.get(i).getTag()); option.setContent(list.get(i).getContent()); options.add(option); } model.setOptions(options); model.setBookId(updated.getBookId()); model.setTopic(updated.getTopic()); return model; } @Transactional(readOnly = true, rollbackFor = { NotFoundException.class }) @Override public Page<Option> findAllOption(Pageable pageable) throws NotFoundException { Page<Option> optionPages = optionRepository.findAll(pageable); return optionPages; } @Transactional @Override public Option addOption(Option added) { LOGGER.debug("Adding a new Objective question entry with information: {}", added); return optionRepository.save(added); } @Transactional(rollbackFor = { NotFoundException.class }) @Override public Option deleteOptionById(Long id) throws NotFoundException { LOGGER.debug("Deleting a to-do entry with id: {}", id); Option deleted = findOptionById(id); LOGGER.debug("Deleting to-do entry: {}", deleted); optionRepository.delete(deleted); return deleted; } @Transactional(readOnly = true, rollbackFor = { NotFoundException.class }) @Override public Option findOptionById(Long id) throws NotFoundException { LOGGER.debug("Finding a to-do entry with id: {}", id); Option found = optionRepository.findOne(id); LOGGER.debug("Found to-do entry: {}", found); if (found == null) { throw new NotFoundException("No to-entry found with id: " + id); } return found; } @Transactional(rollbackFor = { NotFoundException.class }) @Override public Option updateOption(Option updated) throws NotFoundException { LOGGER.debug("Updating contact with information: {}", updated); Option model = findOptionById(updated.getId()); LOGGER.debug("Found a to-do entry: {}", model); model.setContent(updated.getContent()); model.setTag(updated.getTag()); return model; } @Transactional(rollbackFor = { NotFoundException.class }) @Override public ObjectiveQuestion setCorrectOption(Long questionId, Long optionId) throws NotFoundException{ ObjectiveQuestion question = findById(questionId); Option option = findOptionById(optionId); question.setCorrectAnswer(option); return question; } @Transactional(readOnly = true, rollbackFor = { NotFoundException.class }) @Override public Page<CapacityQuestion> findAllCapacityQuestion(Pageable pageable) throws NotFoundException { Page<CapacityQuestion> capacityPages = capacityRepository.findAll(pageable); return capacityPages; } @Transactional(readOnly = true, rollbackFor = { NotFoundException.class }) @Override public Page<SpeedQuestion> findAllSpeedQuestion(Pageable pageable) throws NotFoundException { Page<SpeedQuestion> speedPages = speedRepository.findAll(pageable); return speedPages; } @Transactional @Override public CapacityQuestion addCapacityQuestion(CapacityQuestion added) { LOGGER.debug("Adding a new Objective question entry with information: {}", added); return capacityRepository.save(added); } @Transactional(rollbackFor = { NotFoundException.class }) @Override public CapacityQuestion deleteCapacityQuestionById(Long id) throws NotFoundException { LOGGER.debug("Deleting a to-do entry with id: {}", id); CapacityQuestion deleted = findCapacityQuestionById(id); LOGGER.debug("Deleting to-do entry: {}", deleted); capacityRepository.delete(deleted); return deleted; } @Transactional(readOnly = true, rollbackFor = { NotFoundException.class }) @Override public CapacityQuestion findCapacityQuestionById(Long id) throws NotFoundException { LOGGER.debug("Finding a to-do entry with id: {}", id); CapacityQuestion found = capacityRepository.findOne(id); LOGGER.debug("Found to-do entry: {}", found); if (found == null) { throw new NotFoundException("No to-entry found with id: " + id); } return found; } @Transactional(rollbackFor = { NotFoundException.class }) @Override public CapacityQuestion updateCapacityQuestion(CapacityQuestion updated) throws NotFoundException { LOGGER.debug("Updating contact with information: {}", updated); CapacityQuestion model = findCapacityQuestionById(updated.getId()); LOGGER.debug("Found a to-do entry: {}", model); model.setLevel(updated.getLevel()); model.setQuestionType(updated.getQuestionType()); model.setCorrectAnswer(updated.getCorrectAnswer()); model.setOptions(updated.getOptions()); model.setObjectiveType(updated.getObjectiveType()); model.setTopic(updated.getTopic()); return model; } @Transactional @Override public SpeedQuestion addSpeedQuestion(SpeedQuestion added) { LOGGER.debug("Adding a new Objective question entry with information: {}", added); return speedRepository.save(added); } @Transactional(readOnly = true, rollbackFor = { NotFoundException.class }) @Override public SpeedQuestion findSpeedQuestionById(Long id) throws NotFoundException { LOGGER.debug("Finding a to-do entry with id: {}", id); SpeedQuestion found = speedRepository.findOne(id); LOGGER.debug("Found to-do entry: {}", found); if (found == null) { throw new NotFoundException("No to-entry found with id: " + id); } return found; } @Transactional(rollbackFor = { NotFoundException.class }) @Override public SpeedQuestion deleteSpeedQuestionById(Long id) throws NotFoundException { LOGGER.debug("Deleting a to-do entry with id: {}", id); SpeedQuestion deleted = speedRepository.findOne(id); LOGGER.debug("Deleting to-do entry: {}", deleted); speedRepository.delete(deleted); return deleted; } @Transactional(rollbackFor = { NotFoundException.class }) @Override public SpeedQuestion updateSpeedQuestion(SpeedQuestion updated) throws NotFoundException { LOGGER.debug("Updating contact with information: {}", updated); SpeedQuestion model = speedRepository.findOne(updated.getId()); LOGGER.debug("Found a to-do entry: {}", model); model.setCorrectAnswer(updated.getCorrectAnswer()); model.setOptions(updated.getOptions()); model.setObjectiveType(updated.getObjectiveType()); model.setTopic(updated.getTopic()); return model; } @Transactional @Override public Map<Integer,String> batchSaveOrUpdateObjectiveQuestionFromExcel(Sheet sheet){ ObjectiveQuestion currentQuestion = null; Map<Integer,String> failMap = new HashMap<Integer,String>(); int total = sheet.getPhysicalNumberOfRows(); for(int i=sheet.getFirstRowNum()+1;i<total-1;i++){ Row row = sheet.getRow(i); if(row.getCell(0) == null){ break; } String type = ExcelUtil.getStringFromExcelCell(row.getCell(0)); type=type.trim(); if("词汇测试".equals(type)||"验证测试".equals(type)){ currentQuestion = updateOrSaveQuestionFromRow(failMap,row); }else if("选项".equals(type)){ updateOrSaveOptionFromRow(failMap,row,currentQuestion); }else if("速度测试".equals(type)){ currentQuestion = updateOrSaveSpeedQuestionFromRow(failMap,row); } } return failMap; } private ObjectiveQuestion updateOrSaveQuestionFromRow(Map<Integer,String> map,Row row){ String type = ExcelUtil.getStringFromExcelCell(row.getCell(0)); String topic = ExcelUtil.getStringFromExcelCell(row.getCell(1)); String isbn = ExcelUtil.getStringFromExcelCell(row.getCell(2)); Book book = bookRepository.findByIsbn(isbn); if(book == null){ map.put(row.getRowNum(), "can't find book with isbn:"+isbn); return null; } if(topic.length()>500){ map.put(row.getRowNum(), "Question content is too long, the lenth limit 0-500"); return null; } QuestionType questionType = null; if("词汇测试".equals(type)){ questionType = QuestionType.WORD; }else if("验证测试".equals(type)){ questionType = QuestionType.VERIFY; }else{ questionType = QuestionType.CAPACITY; } ObjectiveQuestion question = repository.findByTopicAndBookIdAndObjectiveType(topic,book.getId(),questionType); if(question == null){ question = new ObjectiveQuestion(); } question.setTopic(topic); question.setObjectiveType(questionType); question.setBookId(book.getId()); return repository.save(question); } private SpeedQuestion updateOrSaveSpeedQuestionFromRow(Map<Integer,String> map,Row row){ String type = ExcelUtil.getStringFromExcelCell(row.getCell(0)); String topic = ExcelUtil.getStringFromExcelCell(row.getCell(1)); long articleId = ExcelUtil.getLongFromExcelCell(row.getCell(2)); if(topic.length()>500){ map.put(row.getRowNum(), "Question content is too long, the lenth limit 0-500"); return null; } QuestionType questionType = QuestionType.SPEED; SpeedQuestion question = speedRepository.findByTopicAndArticleId(topic, articleId); if(question == null){ question = new SpeedQuestion(); } question.setTopic(topic); question.setObjectiveType(questionType); question.setBookId(0L); question.setArticleId(articleId); return repository.save(question); } private void updateOrSaveOptionFromRow(Map<Integer,String>map,Row row,ObjectiveQuestion currentQuestion){ if(currentQuestion == null){ map.put(row.getRowNum(), "Insert Error:Can't connect this option with question"); return; } String content = ExcelUtil.getStringFromExcelCell(row.getCell(1)); String tag = ExcelUtil.getStringFromExcelCell(row.getCell(2)); Option option = new Option(); option.setContent(content); List<Option> options = currentQuestion.getOptions(); option.setTag(tag); if(options!=null){ for(int i=0;i<options.size();i++){ if(options.get(i).getTag().equals(tag)){ option = options.get(i); break; } } }else{ options = new ArrayList<Option>(); } option.setContent(content); options.add(option); String isCorrectAnswer = ExcelUtil.getStringFromExcelCell(row.getCell(3)); if("true".equalsIgnoreCase(isCorrectAnswer.trim())){ currentQuestion.setCorrectAnswer(option); } currentQuestion.setOptions(options); repository.save(currentQuestion); } @Override public Page<ObjectiveQuestion> searchObjectiveQuestionByTopic(String topic, Pageable pageable) { return repository.findByTopicContaining(topic, pageable); } }