/******************************************************************************* * Copyright (c) 2014 antoniomariasanchez at gmail.com. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * antoniomaria - initial API and implementation ******************************************************************************/ package net.sf.gazpachoquest.services.core.impl; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import net.sf.gazpachoquest.domain.core.Question; import net.sf.gazpachoquest.domain.core.QuestionOption; import net.sf.gazpachoquest.domain.core.embeddables.QuestionLanguageSettings; import net.sf.gazpachoquest.domain.i18.QuestionTranslation; import net.sf.gazpachoquest.repository.SectionRepository; import net.sf.gazpachoquest.repository.QuestionRepository; import net.sf.gazpachoquest.repository.QuestionnaireDefinitionRepository; import net.sf.gazpachoquest.repository.i18.QuestionTranslationRepository; import net.sf.gazpachoquest.services.QuestionService; import net.sf.gazpachoquest.types.Language; import org.eclipse.persistence.jpa.JpaEntityManager; import org.eclipse.persistence.sessions.CopyGroup; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; @Service public class QuestionServiceImpl extends AbstractLocalizedPersistenceService<Question, QuestionTranslation, QuestionLanguageSettings> implements QuestionService { @Autowired private SectionRepository sectionRepository; @Autowired private QuestionnaireDefinitionRepository questionnaireDefinitionRepository; @PersistenceContext private EntityManager entityManager; @Autowired public QuestionServiceImpl(final QuestionRepository repository, final QuestionTranslationRepository translationRepository) { super(repository, translationRepository, new QuestionTranslation.Builder()); } @Override @Transactional public Question findOneByPositionInSection(final Integer sectionId, final Integer position) { return ((QuestionRepository) repository).findOneByPositionInSection(sectionId, position); } @Override @Transactional public Integer findPositionInSection(final Integer questionId) { return ((QuestionRepository) repository).findPositionInSection(questionId); } @Override @Transactional public List<Question> findBySectionId(Integer sectionId) { return ((QuestionRepository) repository).findBySectionId(sectionId); } @Override public List<Question> findInList(List<Integer> questionIds) { return ((QuestionRepository) repository).findInList(questionIds); } @Override @Transactional public List<Question> findInList(List<Integer> questionIds, Language language) { if (questionIds.isEmpty()) { return Collections.emptyList(); } List<Question> questions = ((QuestionRepository) repository).findInList(questionIds); if (questions.isEmpty()) { return Collections.emptyList(); } Question sampleQuestion = questions.iterator().next(); // It's assumed that all the question are in the same language boolean isPreferredLanguage = language == null || sampleQuestion.getLanguage().equals(language); CopyGroup group = new CopyGroup(); group.addAttribute("questionOptions"); group.addAttribute("languageSettings"); group.addAttribute("language"); group.addAttribute("type"); group.addAttribute("code"); group.addAttribute("relevance"); group.addAttribute("subquestions.subquestions"); group.addAttribute("subquestions.questionOptions"); group.addAttribute("subquestions.language"); group.addAttribute("subquestions.type"); group.addAttribute("subquestions.code"); group.addAttribute("subquestions.languageSettings"); group.addAttribute("questionOptions.languageSettings"); group.addAttribute("questionOptions.language"); group.addAttribute("questionOptions.code"); // Only load translations is question language is different from // preferred // language if (!isPreferredLanguage) { group.addAttribute("translations"); group.addAttribute("subquestions.translations"); group.addAttribute("questionOptions.translations"); } List<Question> detatchedQuestions = new ArrayList<>(); for (Question question : questions) { Question detatchedQuestion = (Question) entityManager.unwrap(JpaEntityManager.class).copy(question, group); if (!isPreferredLanguage) { detatchedQuestion.translateTo(language); } detatchedQuestions.add(detatchedQuestion); } return sortQuestions(detatchedQuestions, questionIds); } private List<Question> sortQuestions(List<Question> questions, List<Integer> questionIds) { // TODO evaluate guava Ordering.explicit(idList) Map<Integer, Question> map = new LinkedHashMap<>(); List<Question> sortedQuestions = new ArrayList<>(); for (Integer id : questionIds) { map.put(id, Question.with().build()); } for (Question question : questions) { map.put(question.getId(), question); } for (Entry<Integer, Question> entry : map.entrySet()) { sortedQuestions.add(entry.getValue()); } return sortedQuestions; } @Override @Transactional(readOnly = false) public Question save(final Question question) { Assert.state(!question.isNew(), "Question must be already persisted. Try by adding to Section or as added as subquestion first."); Question existing = repository.save(question); for (Question subquestion : question.getSubquestions()) { if (!subquestion.isNew()) { // Skip created subquestions continue; } existing.addSubquestion(subquestion); } for (QuestionOption questionOption : question.getQuestionOptions()) { if (!questionOption.isNew()) { // Skip created questionOptions continue; } existing.addQuestionOption(questionOption); } return existing; } }