/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.platform.questionnaire.ui.model;
import static java.lang.String.format;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.trim;
import static org.mifos.platform.questionnaire.QuestionnaireConstants.DEFAULT_APPLIES_TO_OPTION;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifos.platform.questionnaire.QuestionnaireConstants;
import org.mifos.platform.questionnaire.service.QuestionDetail;
import org.mifos.platform.questionnaire.service.QuestionGroupDetail;
import org.mifos.platform.questionnaire.service.QuestionLinkDetail;
import org.mifos.platform.questionnaire.service.SectionDetail;
import org.mifos.platform.questionnaire.service.SectionLinkDetail;
import org.mifos.platform.questionnaire.service.SectionQuestionDetail;
import org.mifos.platform.questionnaire.service.dtos.EventSourceDto;
import org.mifos.platform.validation.ScreenObject;
@SuppressWarnings("PMD")
public class QuestionGroupForm extends ScreenObject {
private static final long serialVersionUID = -7545625058942409636L;
private QuestionGroupDetail questionGroupDetail;
private SectionDetailForm currentSection = new SectionDetailForm();
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value="SE_BAD_FIELD")
private List<String> selectedQuestionIds = new ArrayList<String>();
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value="SE_BAD_FIELD")
private final List<SectionQuestionDetail> questionPool = new ArrayList<SectionQuestionDetail>();
@javax.validation.Valid
private Question currentQuestion = new Question(new QuestionDetail());
private boolean addQuestionFlag;
private List<SectionDetailForm> sections;
private int initialCountOfSections;
private List<String> sectionsToAdd = new ArrayList<String>();
private List<Integer> questionsToAdd = new ArrayList<Integer>();
private boolean applyToAllLoanProducts;
private List<QuestionLinkDetail> questionLinks = new ArrayList<QuestionLinkDetail>();
private List<SectionLinkDetail> sectionLinks = new ArrayList<SectionLinkDetail>();
public List<QuestionLinkDetail> getQuestionLinks() {
return questionLinks;
}
public void setQuestionLinks(List<QuestionLinkDetail> questionLinks) {
this.questionLinks = questionLinks;
}
public List<SectionLinkDetail> getSectionLinks() {
return sectionLinks;
}
public void setSectionLinks(List<SectionLinkDetail> sectionLinks) {
this.sectionLinks = sectionLinks;
}
public QuestionGroupForm() {
this(new QuestionGroupDetail());
}
public QuestionGroupForm(QuestionGroupDetail questionGroupDetail) {
this.questionGroupDetail = questionGroupDetail;
this.sections = initSections();
}
public QuestionGroupDetail getQuestionGroupDetail() {
return questionGroupDetail;
}
public String getTitle() {
return questionGroupDetail.getTitle();
}
public void setTitle(String title) {
this.questionGroupDetail.setTitle(trim(title));
}
public List<String> getSectionsToAdd() {
return this.sectionsToAdd;
}
public void setSectionsToAdd(List<String> sectionsToAdd) {
this.sectionsToAdd = sectionsToAdd;
}
public List<Integer> getQuestionsToAdd() {
return this.questionsToAdd;
}
public void setQuestionsToAdd(List<Integer> questionsToAdd) {
this.questionsToAdd = questionsToAdd;
}
public List<String> getEventSourceIds() {
List<String> eventSources = new ArrayList<String>();
List<EventSourceDto> eventSourcesDtos = this.questionGroupDetail.getEventSources();
if (eventSourcesDtos == null) {
return eventSources;
}
for (EventSourceDto eventSourceDto : eventSourcesDtos) {
if (eventSourceDto == null || isEmpty(eventSourceDto.getEvent()) || isEmpty(eventSourceDto.getSource())) {
continue;
}
eventSources.add(format("%s.%s", eventSourceDto.getEvent(), eventSourceDto.getSource()));
}
return eventSources;
}
public String getId() {
return questionGroupDetail.getId().toString();
}
public void setEventSourceIds(List<String> eventSourceIds) {
List<EventSourceDto> eventSourceDtos = new ArrayList<EventSourceDto>();
if (eventSourceIds != null) {
for (String eventSourceId : eventSourceIds) {
if (StringUtils.isNotEmpty(eventSourceId) && !StringUtils.equals(DEFAULT_APPLIES_TO_OPTION, eventSourceId)) {
String[] parts = eventSourceId.split("\\.");
eventSourceDtos.add(new EventSourceDto(parts[0], parts[1], eventSourceId));
}
}
}
this.questionGroupDetail.setEventSources(eventSourceDtos);
}
public List<EventSourceDto> getEventSources() {
return questionGroupDetail.getEventSources();
}
public void setEventSources(List<EventSourceDto> eventSourceDtos) {
questionGroupDetail.setEventSources(eventSourceDtos);
}
public List<SectionDetailForm> getSections() {
return this.sections;
}
public void setSections(List<SectionDetailForm> sections) {
List<SectionDetail> sectionDetails = new ArrayList<SectionDetail>();
this.sections = new ArrayList<SectionDetailForm>();
for (SectionDetailForm sectionDetailForm : sections) {
this.sections.add(sectionDetailForm);
sectionDetails.add(sectionDetailForm.getSectionDetail());
}
questionGroupDetail.setSectionDetails(sectionDetails);
}
public void addCurrentSection() {
currentSection.trimName();
String sectionName = getSectionName();
addCurrentSectionToSections();
if (addQuestionFlag) {
addNewQuestion();
} else {
addSelectedQuestionsToCurrentSection();
}
currentSection = new SectionDetailForm();
currentSection.setName(sectionName);
selectedQuestionIds = new ArrayList<String>();
}
private void addSelectedQuestionsToCurrentSection() {
List<SectionQuestionDetail> addedQuestions = new ArrayList<SectionQuestionDetail>();
for (SectionQuestionDetail questionDetail : questionPool) {
if (selectedQuestionIds.contains(String.valueOf(questionDetail.getQuestionId()))) {
questionDetail.setSequenceNumber(currentSection.getSectionQuestionDetails().size());
currentSection.addSectionQuestion(questionDetail);
addedQuestions.add(questionDetail);
questionsToAdd.add(questionDetail.getQuestionId());
}
}
questionPool.removeAll(addedQuestions);
}
private void addNewQuestion() {
currentQuestion.setChoices();
SectionQuestionDetail sectionQuestionDetail = new SectionQuestionDetail(currentQuestion.getQuestionDetail(), false);
currentSection.addSectionQuestion(sectionQuestionDetail);
Integer newQuestionId = getNewQuestionId();
sectionQuestionDetail.getQuestionDetail().setId(newQuestionId);
currentQuestion = new Question(new QuestionDetail());
questionsToAdd.add(newQuestionId);
updateSequenceNumbers();
}
private Integer getNewQuestionId() {
Integer minId = 0;
List<SectionQuestionDetail> sectionQuestionDetails = currentSection.getSectionQuestionDetails();
for (SectionQuestionDetail sectionQuestionDetail : sectionQuestionDetails) {
if (sectionQuestionDetail.getQuestionId() < minId) {
minId = sectionQuestionDetail.getQuestionId();
}
}
return minId - 1;
}
private void updateSequenceNumbers() {
List<SectionQuestionDetailForm> questions = currentSection.getSectionQuestions();
int sequenceNumber = 0;
for (SectionQuestionDetailForm sectionQuestionDetailForm : questions) {
sectionQuestionDetailForm.setSequenceNumber(sequenceNumber++);
}
}
public boolean isDuplicateText(String questionTitle) {
boolean result = false;
if(StringUtils.isNotEmpty(questionTitle)){
for (SectionQuestionDetail sectionQuestionDetail : getAllQuestionsInAllSections()) {
if(StringUtils.equalsIgnoreCase(questionTitle, sectionQuestionDetail.getText())){
result = true;
break;
}
}
}
return result;
}
private List<SectionQuestionDetail> getAllQuestionsInAllSections() {
List<SectionQuestionDetail> sectionQuestionDetails = new ArrayList<SectionQuestionDetail>();
for (SectionDetail sectionDetail : questionGroupDetail.getSectionDetails()) {
sectionQuestionDetails.addAll(sectionDetail.getQuestions());
}
return sectionQuestionDetails;
}
private void addCurrentSectionToSections() {
for (SectionDetailForm section : sections) {
if (StringUtils.equalsIgnoreCase(section.getName(), currentSection.getName())) {
currentSection = section;
return;
}
}
List<SectionDetail> sectionDetails = new ArrayList<SectionDetail>();
for (SectionDetailForm sectionDetailForm : sections) {
SectionDetail sectionDetail = sectionDetailForm.getSectionDetail();
sectionDetail.setSequenceNumber(sectionDetail.getSequenceNumber() + 1);
sectionDetails.add(sectionDetail);
}
currentSection.getSectionDetail().setSequenceNumber(0);
sectionDetails.add(0, currentSection.getSectionDetail());
sections.add(0, currentSection);
questionGroupDetail.setSectionDetails(sectionDetails);
sectionsToAdd.add(currentSection.getName());
}
public String getSectionName() {
if (StringUtils.isEmpty(currentSection.getName())) {
currentSection.setName(QuestionnaireConstants.DEFAULT_SECTION_NAME);
}
return currentSection.getName();
}
public void setSectionName(String sectionName) {
currentSection.setName(sectionName);
}
public void removeSection(String sectionName) {
SectionDetail sectionToDelete = null;
for (Iterator<SectionDetailForm> iterator = sections.iterator(); iterator.hasNext();) {
SectionDetailForm section = iterator.next();
if (StringUtils.equalsIgnoreCase(sectionName, section.getName())) {
sectionToDelete = section.getSectionDetail();
iterator.remove();
break;
}
}
if (sectionToDelete != null) {
List<SectionDetail> sectionDetails = new ArrayList<SectionDetail>();
int sequence = 0;
for (SectionDetailForm sectionDetailForm : sections) {
SectionDetail sectionDetail = sectionDetailForm.getSectionDetail();
sectionDetail.setSequenceNumber(sequence++);
sectionDetails.add(sectionDetail);
}
markQuestionsOptionalAndReturnToPool(sectionToDelete);
questionGroupDetail.setSectionDetails(sectionDetails);
for (int i = 0; i < sectionsToAdd.size(); i++) {
String name = sectionsToAdd.get(i);
if (name.equals(sectionName)) {
sectionsToAdd.remove(i);
break;
}
}
for(Iterator<SectionLinkDetail> iterator = sectionLinks.iterator(); iterator.hasNext();){
SectionLinkDetail sectionLinkDetail = iterator.next();
if(sectionLinkDetail.getAffectedSection().getName().equals(sectionToDelete.getName()))
iterator.remove();
for(SectionQuestionDetail sectionQuestionDetail : sectionToDelete.getQuestionDetails()){
if(sectionLinkDetail.getSourceQuestion().getQuestionDetail().getId().equals(sectionQuestionDetail.getQuestionDetail().getId()))
iterator.remove();
}
}
for(SectionQuestionDetail sectionQuestionDetail : sectionToDelete.getQuestionDetails()){
for(Iterator<QuestionLinkDetail> iterator = questionLinks.iterator(); iterator.hasNext();){
QuestionLinkDetail questionLinkDetail = iterator.next();
if(questionLinkDetail.getSourceQuestion().getQuestionDetail().getId().equals(sectionQuestionDetail.getQuestionId()))
iterator.remove();
if(questionLinkDetail.getAffectedQuestion().getQuestionDetail().getId().equals(sectionQuestionDetail.getQuestionId()))
iterator.remove();
}
}
}
}
private void markQuestionsOptionalAndReturnToPool(SectionDetail sectionDetail) {
List<SectionQuestionDetail> sectionQuestionDetails = sectionDetail.getQuestions();
for(SectionQuestionDetail sectionQuestionDetail: sectionQuestionDetails){
sectionQuestionDetail.setMandatory(false);
questionPool.add(sectionQuestionDetail);
}
}
public List<SectionQuestionDetail> getQuestionPool() {
return questionPool;
}
public void setQuestionPool(List<SectionQuestionDetail> questionPool) {
this.questionPool.clear();
this.questionPool.addAll(questionPool);
}
public List<String> getSelectedQuestionIds() {
return selectedQuestionIds;
}
public void setSelectedQuestionIds(List<String> selectedQuestionIds) {
this.selectedQuestionIds = selectedQuestionIds;
}
public void removeQuestion(String sectionName, String questionId) {
for (SectionDetail sectionDetail : questionGroupDetail.getSectionDetails()) {
if (StringUtils.equalsIgnoreCase(sectionName, sectionDetail.getName())) {
removeQuestionFromSection(questionId, sectionDetail);
for (int i = 0; i < questionsToAdd.size(); i++) {
int name = questionsToAdd.get(i);
if (name == Integer.parseInt(questionId)) {
questionsToAdd.remove(i);
break;
}
}
if (sectionHasNoQuestions(sectionDetail)) {
removeSection(sectionName);
}
break;
}
}
for(Iterator<SectionLinkDetail> iterator = sectionLinks.iterator(); iterator.hasNext();){
SectionLinkDetail sectionLinkDetail = iterator.next();
if(sectionLinkDetail.getSourceQuestion().getQuestionDetail().getId().equals(Integer.valueOf(questionId)))
iterator.remove();
}
for(Iterator<QuestionLinkDetail> iterator = questionLinks.iterator(); iterator.hasNext();){
QuestionLinkDetail questionLinkDetail = iterator.next();
if(questionLinkDetail.getSourceQuestion().getQuestionDetail().getId().equals(Integer.valueOf(questionId)))
iterator.remove();
if(questionLinkDetail.getAffectedQuestion().getQuestionDetail().getId().equals(Integer.valueOf(questionId)))
iterator.remove();
}
}
public void moveQuestionUp(String sectionName, String questionId) {
for (SectionDetailForm section : sections) {
if (StringUtils.equalsIgnoreCase(sectionName, section.getName())) {
List<SectionQuestionDetail> questions = section.getSectionQuestionDetails();
for (SectionQuestionDetail question : questions) {
if (Integer.parseInt(questionId) == question.getQuestionId()) {
int actualSeqNumber = question.getSequenceNumber();
if (actualSeqNumber > 0) {
SectionQuestionDetail questionToSwap = questions.get(actualSeqNumber - 1);
question.setSequenceNumber(questionToSwap.getSequenceNumber());
questionToSwap.setSequenceNumber(actualSeqNumber);
questions.set(actualSeqNumber, questionToSwap);
questions.set(actualSeqNumber - 1, question);
}
break;
}
}
break;
}
}
}
public void moveQuestionDown(String sectionName, String questionId) {
for (SectionDetailForm section : sections) {
if (StringUtils.equalsIgnoreCase(sectionName, section.getName())) {
List<SectionQuestionDetail> questions = section.getSectionQuestionDetails();
for (SectionQuestionDetail question : questions) {
if (Integer.parseInt(questionId) == question.getQuestionId()) {
int actualSeqNumber = question.getSequenceNumber();
if (actualSeqNumber < questions.size() - 1) {
SectionQuestionDetail questionToSwap = questions.get(actualSeqNumber + 1);
question.setSequenceNumber(questionToSwap.getSequenceNumber());
questionToSwap.setSequenceNumber(actualSeqNumber);
questions.set(actualSeqNumber, questionToSwap);
questions.set(actualSeqNumber + 1, question);
}
break;
}
}
break;
}
}
}
public void moveSectionUp(String sectionName) {
for (SectionDetailForm sectionForm : sections) {
SectionDetail section = sectionForm.getSectionDetail();
if (StringUtils.equalsIgnoreCase(sectionName, section.getName())) {
int actualSeqNumber = section.getSequenceNumber();
if (actualSeqNumber > 0) {
SectionDetailForm sectionToSwap = sections.remove(actualSeqNumber - 1);
section.setSequenceNumber(sectionToSwap.getSectionDetail().getSequenceNumber());
sectionToSwap.getSectionDetail().setSequenceNumber(actualSeqNumber);
sections.add(actualSeqNumber - 1, sectionForm);
sections.set(actualSeqNumber, sectionToSwap);
List<SectionDetail> sectionDetails = new ArrayList<SectionDetail>();
for (SectionDetailForm sectionDetailForm : sections) {
sectionDetails.add(sectionDetailForm.getSectionDetail());
}
questionGroupDetail.setSectionDetails(sectionDetails);
}
break;
}
}
}
public void moveSectionDown(String sectionName) {
for (SectionDetailForm sectionForm : sections) {
SectionDetail section = sectionForm.getSectionDetail();
if (StringUtils.equalsIgnoreCase(sectionName, section.getName())) {
int actualSeqNumber = section.getSequenceNumber();
if (actualSeqNumber < sections.size() - 1) {
SectionDetailForm sectionToSwap = sections.remove(actualSeqNumber + 1);
section.setSequenceNumber(sectionToSwap.getSectionDetail().getSequenceNumber());
sectionToSwap.getSectionDetail().setSequenceNumber(actualSeqNumber);
sections.add(actualSeqNumber + 1, sectionForm);
sections.set(actualSeqNumber, sectionToSwap);
List<SectionDetail> sectionDetails = new ArrayList<SectionDetail>();
for (SectionDetailForm sectionDetailForm : sections) {
sectionDetails.add(sectionDetailForm.getSectionDetail());
}
questionGroupDetail.setSectionDetails(sectionDetails);
}
break;
}
}
}
public boolean hasNoQuestionsInCurrentSection() {
return selectedQuestionIds.size() == 0;
}
private boolean sectionHasNoQuestions(SectionDetail section) {
return section.getQuestions().size() == 0;
}
private void removeQuestionFromSection(String questionId, SectionDetail section) {
SectionQuestionDetail questionToRemove = null;
List<SectionQuestionDetail> questions = section.getQuestions();
for (SectionQuestionDetail question : questions) {
if (StringUtils.equals(questionId, String.valueOf(question.getQuestionId()))) {
questionToRemove = question;
break;
}
}
if (questionToRemove != null) {
questionToRemove.setMandatory(false);
questionToRemove.setSequenceNumber(0);
questions.remove(questionToRemove);
int sequence = 0;
for (SectionQuestionDetail sectionQuestionDetail : questions) {
sectionQuestionDetail.setSequenceNumber(sequence++);
}
questionPool.add(questionToRemove);
}
}
public boolean isEditable() {
return questionGroupDetail.isEditable();
}
public void setEditable(boolean editable) {
questionGroupDetail.setEditable(editable);
}
public boolean isActive() {
return questionGroupDetail.isActive();
}
public void setActive(boolean active) {
questionGroupDetail.setActive(active);
}
public Question getCurrentQuestion() {
return currentQuestion;
}
public void setCurrentQuestion(Question currentQuestion) {
this.currentQuestion = currentQuestion;
}
public boolean isAddQuestionFlag() {
return addQuestionFlag;
}
public void setAddQuestionFlag(boolean addQuestionFlag) {
this.addQuestionFlag = addQuestionFlag;
}
public void setQuestionGroupDetail(QuestionGroupDetail questionGroupDetail) {
this.questionGroupDetail = questionGroupDetail;
this.sections = initSections();
this.sectionLinks = questionGroupDetail.getSectionLinks();
this.questionLinks= questionGroupDetail.getQuestionLinks();
}
private List<SectionDetailForm> initSections() {
List<SectionDetailForm> sectionDetailForms = new ArrayList<SectionDetailForm>();
if (questionGroupDetail != null) {
for (SectionDetail sectionDetail : questionGroupDetail.getSectionDetails()) {
SectionDetailForm sectionDetailForm = new SectionDetailForm(sectionDetail);
sectionDetailForm.setInitialCountOfQuestions(sectionDetail.getCountOfQuestions());
sectionDetailForms.add(sectionDetailForm);
}
}
this.initialCountOfSections = sectionDetailForms.size();
return sectionDetailForms;
}
public int getInitialCountOfSections() {
return initialCountOfSections;
}
public boolean getApplyToAllLoanProducts() {
return applyToAllLoanProducts;
}
public void setApplyToAllLoanProducts(boolean applyToAllLoanProducts) {
this.applyToAllLoanProducts = applyToAllLoanProducts;
}
}