org.ednovo.gooru.domain.service.assessment.AssessmentServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.ednovo.gooru.domain.service.assessment.AssessmentServiceImpl.java

Source

/////////////////////////////////////////////////////////////
// AssessmentServiceImpl.java
// gooru-api
// Created by Gooru on 2014
// Copyright (c) 2014 Gooru. All rights reserved.
// http://www.goorulearning.org/
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/////////////////////////////////////////////////////////////
package org.ednovo.gooru.domain.service.assessment;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.ednovo.gooru.application.util.AsyncExecutor;
import org.ednovo.gooru.application.util.CollectionUtil;
import org.ednovo.gooru.application.util.ResourceImageUtil;
import org.ednovo.gooru.core.api.model.ActionResponseDTO;
import org.ednovo.gooru.core.api.model.AssessmentAnswer;
import org.ednovo.gooru.core.api.model.AssessmentHint;
import org.ednovo.gooru.core.api.model.AssessmentQuestion;
import org.ednovo.gooru.core.api.model.AssessmentQuestionAssetAssoc;
import org.ednovo.gooru.core.api.model.Asset;
import org.ednovo.gooru.core.api.model.Code;
import org.ednovo.gooru.core.api.model.ContentMetaDTO;
import org.ednovo.gooru.core.api.model.ContentType;
import org.ednovo.gooru.core.api.model.License;
import org.ednovo.gooru.core.api.model.QuestionSet;
import org.ednovo.gooru.core.api.model.QuestionSetQuestionAssoc;
import org.ednovo.gooru.core.api.model.Resource;
import org.ednovo.gooru.core.api.model.ResourceSource;
import org.ednovo.gooru.core.api.model.ResourceType;
import org.ednovo.gooru.core.api.model.User;
import org.ednovo.gooru.core.application.util.ErrorMessage;
import org.ednovo.gooru.core.application.util.ResourceMetaInfo;
import org.ednovo.gooru.core.application.util.ServerValidationUtils;
import org.ednovo.gooru.core.constant.ConstantProperties;
import org.ednovo.gooru.core.constant.Constants;
import org.ednovo.gooru.core.constant.ParameterProperties;
import org.ednovo.gooru.core.exception.BadRequestException;
import org.ednovo.gooru.core.exception.NotFoundException;
import org.ednovo.gooru.domain.service.CollectionService;
import org.ednovo.gooru.domain.service.content.ContentService;
import org.ednovo.gooru.domain.service.resource.AssetManager;
import org.ednovo.gooru.domain.service.resource.ResourceManager;
import org.ednovo.gooru.domain.service.resource.ResourceService;
import org.ednovo.gooru.domain.service.storage.S3ResourceApiHandler;
import org.ednovo.gooru.domain.service.taxonomy.TaxonomyService;
import org.ednovo.gooru.domain.service.user.UserService;
import org.ednovo.gooru.infrastructure.messenger.IndexHandler;
import org.ednovo.gooru.infrastructure.messenger.IndexProcessor;
import org.ednovo.gooru.infrastructure.persistence.hibernate.BaseRepository;
import org.ednovo.gooru.infrastructure.persistence.hibernate.UserRepository;
import org.ednovo.gooru.infrastructure.persistence.hibernate.assessment.AssessmentRepository;
import org.ednovo.gooru.infrastructure.persistence.hibernate.content.ContentRepository;
import org.ednovo.gooru.infrastructure.persistence.hibernate.customTable.CustomTableRepository;
import org.ednovo.gooru.infrastructure.persistence.hibernate.resource.ResourceRepository;
import org.ednovo.gooru.infrastructure.persistence.hibernate.taxonomy.TaxonomyRespository;
import org.ednovo.gooru.infrastructure.persistence.hibernate.taxonomy.TaxonomyStoredProcedure;
import org.ednovo.gooru.mongodb.assessments.questions.services.MongoQuestionsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;

@Service
public class AssessmentServiceImpl implements ConstantProperties, AssessmentService, ParameterProperties {

    @Autowired
    private AssessmentRepository assessmentRepository;

    @Autowired
    private BaseRepository baseRepository;

    @Autowired
    private ResourceRepository resourceRepository;

    @Autowired
    ResourceImageUtil resourceImageUtil;

    @Autowired
    private TaxonomyStoredProcedure procedureExecutor;

    @Autowired
    private TaxonomyRespository taxonomyRepository;

    @Autowired
    private TaxonomyService taxonomyService;

    @Autowired
    @javax.annotation.Resource(name = "assetManager")
    private AssetManager assetManager;

    @Autowired
    private S3ResourceApiHandler s3ResourceApiHandler;

    @Autowired
    CollectionUtil collectionUtil;

    @Autowired
    private IndexProcessor indexProcessor;

    private static final Logger LOGGER = LoggerFactory.getLogger(AssessmentServiceImpl.class);

    @Autowired
    private ContentRepository contentRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    @javax.annotation.Resource(name = "resourceManager")
    private ResourceManager resourceManager;

    @Autowired
    private ContentService contentService;

    @Autowired
    private UserService userService;

    @Autowired
    private CustomTableRepository customTableRepository;

    @Autowired
    private AsyncExecutor asyncExecutor;

    @Autowired
    private CollectionService collectionService;

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private IndexHandler indexHandler;

    @Autowired
    private MongoQuestionsService mongoQuestionsService;

    @Override
    public AssessmentQuestion getQuestion(String gooruOQuestionId) {
        return (AssessmentQuestion) assessmentRepository.getByGooruOId(AssessmentQuestion.class, gooruOQuestionId);
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResponseDTO<AssessmentQuestion> createQuestion(AssessmentQuestion question, boolean index)
            throws Exception {
        Set<Code> taxonomy = question.getTaxonomySet();
        question = initQuestion(question, null, true);
        question.setIsOer(1);
        question.setTaxonomySet(null);
        Errors errors = validateQuestion(question);
        if (!errors.hasErrors()) {
            // To Save Folder
            question.setOrganization(question.getCreator().getOrganization());
            assessmentRepository.save(question);
            resourceService.saveOrUpdateResourceTaxonomy(question, taxonomy);
            if (question.getResourceInfo() != null) {
                resourceRepository.save(question.getResourceInfo());
            }
            s3ResourceApiHandler.updateOrganization(question);

            if (index) {
                try {
                    indexHandler.setReIndexRequest(question.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null,
                            false, false);
                } catch (Exception e) {
                    LOGGER.info(e.getMessage());
                }
            }
        }
        return new ActionResponseDTO<AssessmentQuestion>(question, errors);
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResponseDTO<AssessmentQuestion> updateQuestion(AssessmentQuestion question,
            List<Integer> deleteAssets, String gooruOQuestionId, boolean copyToOriginal, boolean index)
            throws Exception {
        AssessmentQuestion incomingQuestion = question;
        question = initQuestion(question, gooruOQuestionId, copyToOriginal);
        Errors errors = validateQuestion(question);
        List<Asset> assets = buildQuestionAssets(deleteAssets, errors);

        if (!errors.hasErrors()) {
            assessmentRepository.save(question);
            if (question.getResourceInfo() != null) {
                resourceRepository.save(question.getResourceInfo());
            }

            for (Asset asset : assets) {
                assessmentRepository.deleteQuestionAssets(asset.getAssetId());
                assetManager.deletePathIfExist(asset.getOrganization().getNfsStorageArea().getInternalPath()
                        + question.getFolder() + asset.getName());
            }
            /*
             * Remove the assets for the new generation question. These assets
             * are in not stored in association in mysql. Since the question is
             * getting overridden we need to use original object (as we are
             * using transient field).
             */
            if (incomingQuestion.isQuestionNewGen()) {
                List<String> deletedMediaFiles = incomingQuestion.getDeletedMediaFiles();
                if (deletedMediaFiles != null && deletedMediaFiles.size() > 0) {
                    for (String deletedMediaFile : deletedMediaFiles) {
                        assetManager
                                .deletePathIfExist(question.getOrganization().getNfsStorageArea().getInternalPath()
                                        + question.getFolder() + deletedMediaFile);
                    }
                }
            }
            if (assets.size() > 0) {
                assessmentRepository.removeAll(assets);
            }

            ResourceMetaInfo resourceMetaInfo = new ResourceMetaInfo();
            resourceMetaInfo.setStandards(collectionService.getStandards(question.getTaxonomySet(), false, null));
            question.setMetaInfo(resourceMetaInfo);
            updateQuestionTime(question);
            if (index) {
                indexHandler.setReIndexRequest(question.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false,
                        false);
            }
        }

        return new ActionResponseDTO<AssessmentQuestion>(question, errors);
    }

    private List<Asset> buildQuestionAssets(List<Integer> assets, Errors errors) {
        List<Asset> assetList = new ArrayList<Asset>();
        if (assets != null) {
            for (Integer assetId : assets) {
                Asset asset = (Asset) assessmentRepository.getModel(Asset.class, assetId);
                if (asset != null) {
                    assetList.add(asset);
                }
            }
        }
        return assetList;
    }

    private AssessmentQuestion initQuestion(AssessmentQuestion question, String gooruOQuestionId,
            boolean copyToOriginal) {
        if (copyToOriginal) {
            if (gooruOQuestionId == null) {
                License license = (License) baseRepository.get(License.class, CREATIVE_COMMONS);
                question.setLicense(license);
                ContentType contentType = (ContentType) baseRepository.get(ContentType.class, ContentType.QUESTION);
                question.setContentType(contentType);
                if (question.getGooruOid() == null) {
                    question.setGooruOid(UUID.randomUUID().toString());
                }
                ServerValidationUtils.rejectIfNull(question.getQuestionText(), GL0006, QUESTION_TEXT);
                question.setTitle(question.getQuestionText().substring(0,
                        question.getQuestionText().length() > 1000 ? 999 : question.getQuestionText().length()));
                // Explicitly set to null to reset any content id sent by
                // clients
                question.setContentId(null);
                question.setCreatedOn(new java.util.Date());
                question.setUrl("");
                if (question.getSharing() == null) {
                    question.setSharing(PUBLIC);
                }
                if (question.getDistinguish() == null) {
                    question.setDistinguish(Short.valueOf("0"));
                }
                if (question.getIsFeatured() == null) {
                    question.setIsFeatured(0);
                }
                if (question.getTypeName() == null) {
                    question.setTypeName(AssessmentQuestion.TYPE.MULTIPLE_CHOICE.getName());
                }
                if (question.getTypeName().equalsIgnoreCase(AssessmentQuestion.TYPE.MATCH_THE_FOLLOWING.getName())
                        && question.getAnswers().size() > 0) {
                    for (AssessmentAnswer assessmentAnswer : question.getAnswers()) {
                        for (AssessmentAnswer matchingAnswer : question.getAnswers()) {
                            if (assessmentAnswer.getMatchingSequence() != null
                                    && assessmentAnswer.getMatchingSequence()
                                            .equals(matchingAnswer.getMatchingSequence())
                                    && !assessmentAnswer.getSequence().equals(matchingAnswer.getSequence())) {
                                // assessmentAnswer.setMatchingAnswer(matchingAnswer);
                                matchingAnswer.setMatchingAnswer(assessmentAnswer);
                            }
                        }
                    }
                }
                ResourceType resourceType = null;
                if (question.getSourceReference() != null
                        && question.getSourceReference().equalsIgnoreCase(ASSESSMENT)) {
                    resourceType = (ResourceType) baseRepository.get(ResourceType.class,
                            ResourceType.Type.AM_ASSESSMENT_QUESTION.getType());
                } else {
                    resourceType = (ResourceType) baseRepository.get(ResourceType.class,
                            ResourceType.Type.ASSESSMENT_QUESTION.getType());
                }
                question.setResourceType(resourceType);
                question.setTypeName(question.getTypeName());
                question.setCategory(QUESTION);
                question.setResourceFormat(
                        this.getCustomTableRepository().getCustomTableValue(RESOURCE_CATEGORY_FORMAT, QUESTION));
            } else {
                AssessmentQuestion existingQuestion = getQuestion(gooruOQuestionId);
                if (existingQuestion == null) {
                    throw new NotFoundException(ServerValidationUtils.generateErrorMessage(GL0056, RESOURCE),
                            GL0056);
                }

                if (question.getQuestionText() != null) {
                    existingQuestion.setQuestionText(question.getQuestionText());
                    existingQuestion.setTitle(
                            question.getQuestionText().substring(0, question.getQuestionText().length() > 1000 ? 999
                                    : question.getQuestionText().length()));
                }
                if (question.getDescription() != null) {
                    existingQuestion.setDescription(question.getDescription());
                }
                if (question.getExplanation() != null) {
                    existingQuestion.setExplanation(question.getExplanation());
                }
                if (question.getConcept() != null) {
                    existingQuestion.setConcept(question.getConcept());
                }
                if (question.getImportCode() != null) {
                    existingQuestion.setImportCode(question.getImportCode());
                }
                if (question.getContentType() != null) {
                    existingQuestion.setContentType(question.getContentType());
                }
                if (question.getTags() != null) {
                    existingQuestion.setTags(question.getTags());
                }
                if (question.getResourceSource() != null && existingQuestion.getResourceSource() != null) {
                    ResourceSource resourceSource = existingQuestion.getResourceSource();
                    resourceSource.setAttribution(question.getResourceSource().getAttribution());
                    existingQuestion.setResourceSource(resourceSource);
                }
                existingQuestion.setDifficultyLevel(question.getDifficultyLevel());

                if (question.getTitle() != null) {
                    existingQuestion.setTitle(question.getTitle());
                }
                existingQuestion.setTimeToCompleteInSecs(question.getTimeToCompleteInSecs());
                if (question.getTypeName() != null) {
                    existingQuestion.setTypeName(question.getTypeName());
                }
                if (question.getCategory() != null) {
                    existingQuestion.setCategory(question.getCategory());
                }
                if (question.getSharing() != null) {
                    existingQuestion.setSharing(question.getSharing());
                }
                if (question.getAnswers() != null) {
                    updateAnswerList(question.getAnswers(), existingQuestion.getAnswers());
                }
                if (question.getHints() != null) {
                    updateHintList(question.getHints(), existingQuestion.getHints());
                }
                resourceService.saveOrUpdateResourceTaxonomy(existingQuestion, question.getTaxonomySet());

                if (question.getRecordSource() != null) {
                    existingQuestion.setRecordSource(question.getRecordSource());
                }

                question = existingQuestion;
            }
        }
        question.setLastModified(new java.util.Date());

        if (question.getConcept() == null) {
            question.setConcept("");
        }

        if (question.getRecordSource() == null) {
            question.setRecordSource(Resource.RecordSource.DEFAULT.getRecordSource());
        }

        if (question.getTimeToCompleteInSecs() == null) {
            question.setTimeToCompleteInSecs(0);
        }

        if (question.getExplanation() == null) {
            question.setExplanation("");
        }
        if (question.getDescription() == null) {
            question.setDescription("");
        }
        if (question.getSharing() == null) {
            question.setSharing(PUBLIC);
        }
        if (question.getLicense() == null) {
            question.setLicense(new License());
            question.getLicense().setName(CREATIVE_COMMONS);
        }
        if (question.getUrl() == null) {
            question.setUrl("");
        }

        if (question.getQuestionText() == null) {
            throw new BadRequestException("Question Text is mandatory");

        }

        return question;
    }

    private void updateAnswerList(Set<AssessmentAnswer> sourceList, Set<AssessmentAnswer> existingList) {
        Set<AssessmentAnswer> addList = new TreeSet<AssessmentAnswer>();
        if (sourceList != null && sourceList.size() > 0) {
            if (existingList != null && existingList.size() > 0) {
                for (AssessmentAnswer srcObj : sourceList) {
                    for (AssessmentAnswer chkObj : existingList) {
                        if (srcObj.getAnswerId() != null) {
                            if (srcObj.getAnswerId().equals(chkObj.getAnswerId())) {
                                chkObj.setAnswerText(srcObj.getAnswerText());
                                chkObj.setAnswerType(srcObj.getAnswerType());
                                chkObj.setIsCorrect(srcObj.getIsCorrect());
                                chkObj.setUnit(srcObj.getUnit());
                                addList.add(chkObj);
                                break;
                            }
                        } else if (!addList.contains(srcObj)) {
                            addList.add(srcObj);
                            if (srcObj.getIsCorrect() == null) {
                                srcObj.setIsCorrect(false);
                            }
                        }
                    }
                }
            } else {
                addList.addAll(sourceList);
            }
        }
        existingList.clear();
        existingList.addAll(addList);
    }

    private void updateHintList(Set<AssessmentHint> sourceList, Set<AssessmentHint> existingList) {
        Set<AssessmentHint> addList = new TreeSet<AssessmentHint>();
        if (sourceList != null && sourceList.size() > 0) {
            if (existingList != null && existingList.size() > 0) {
                for (AssessmentHint srcObj : sourceList) {
                    for (AssessmentHint chkObj : existingList) {
                        if (srcObj.getHintId() != null) {
                            if (srcObj.getHintId().equals(chkObj.getHintId())) {
                                chkObj.setHintText(srcObj.getHintText());
                                addList.add(chkObj);
                                break;
                            }
                        } else if (!addList.contains(srcObj)) {
                            addList.add(srcObj);
                        }
                    }
                }
            } else {
                addList.addAll(sourceList);
            }
        }
        existingList.clear();
        existingList.addAll(addList);
    }

    @Override
    public void updateQuetionInfo(String gooruOQuestionId, Integer segmentId) {
        updateQuestionTime(getQuestion(gooruOQuestionId));
    }

    private void updateQuestionTime(AssessmentQuestion question) {
        if (question != null) {
            assessmentRepository.updateTimeForSegments(question.getContentId());
            assessmentRepository.updateTimeForAssessments(question.getContentId());
        }
    }

    @Override
    public boolean getAttemptAnswerStatus(Integer answerId) {
        return assessmentRepository.getAttemptAnswerStatus(answerId);
    }

    private Errors validateQuestion(AssessmentQuestion question) throws Exception {
        final Errors errors = new BindException(question, QUESTION);
        if (question != null) {
            boolean imageExist = false;
            if (question.getAssets() != null) {
                for (AssessmentQuestionAssetAssoc assetAssoc : question.getAssets()) {
                    if (assetAssoc.getAssetKey().equals(ASSET_QUESTION)) {
                        imageExist = true;
                    }
                }
            }
            if (!imageExist) {
                ServerValidationUtils.rejectIfNullOrEmpty(errors, question.getQuestionText(), QUESTION_TEXT,
                        ErrorMessage.REQUIRED_FIELD);
            }
            if (question.getTypeName().equals(AssessmentQuestion.TYPE.SHORT_ANSWER.getName())
                    && question.getTypeName().equals(AssessmentQuestion.TYPE.OPEN_ENDED.getName())) {
                ServerValidationUtils.rejectIfNullOrEmpty(errors, question.getAnswers(), ANSWERS,
                        ErrorMessage.REQUIRED_FIELD);
            }
        }
        return errors;
    }

    @Override
    public QuestionSet getQuestionSet(String gooruOQuestionSetId) {
        return assessmentRepository.getByGooruOId(QuestionSet.class, gooruOQuestionSetId);
    }

    @Override
    public ActionResponseDTO<QuestionSet> createQuestionSet(QuestionSet questionSet) throws Exception {

        questionSet = initQuestionSet(questionSet, null);

        Errors errors = validateQuestionSet(questionSet);

        if (!errors.hasErrors()) {
            assessmentRepository.save(questionSet);
        }

        return new ActionResponseDTO<QuestionSet>(questionSet, errors);
    }

    @Override
    public ActionResponseDTO<QuestionSet> updateQuestionSet(QuestionSet questionSet, String gooruOQuestionSetId)
            throws Exception {
        questionSet = initQuestionSet(questionSet, gooruOQuestionSetId);

        Errors errors = validateQuestionSet(questionSet);

        if (!errors.hasErrors()) {
            assessmentRepository.save(questionSet);
        }

        return new ActionResponseDTO<QuestionSet>(questionSet, errors);
    }

    private QuestionSet initQuestionSet(QuestionSet questionSet, String gooruOQuestionSetId) {
        if (gooruOQuestionSetId == null) {
            License license = (License) baseRepository.get(License.class, OTHER);
            questionSet.setLicense(license);
            questionSet.setGooruOid(UUID.randomUUID().toString());
            questionSet.setContentId(null);
            questionSet.setCreatedOn(new java.util.Date());
            questionSet.setUrl("");
            ContentType contentType = (ContentType) baseRepository.get(ContentType.class, ContentType.RESOURCE);
            questionSet.setContentType(contentType);
        } else {
            QuestionSet existingQuestionSet = getQuestionSet(gooruOQuestionSetId);
            existingQuestionSet.setTitle(questionSet.getTitle());

            questionSet = existingQuestionSet;
        }
        ResourceType resourceType = (ResourceType) baseRepository.get(ResourceType.class,
                questionSet.getResourceType().getName());
        questionSet.setResourceType(resourceType);
        questionSet.setLastModified(new java.util.Date());
        return questionSet;
    }

    private Errors validateQuestionSet(QuestionSet questionSet) throws Exception {
        final Errors errors = new BindException(questionSet, QUESTION_SET);
        if (questionSet != null) {
            ServerValidationUtils.rejectIfNullOrEmpty(errors, questionSet.getTitle(), TITLE,
                    ErrorMessage.REQUIRED_FIELD);
        }
        return errors;
    }

    @Override
    public List<QuestionSet> listQuestionSets(Map<String, String> filters) {
        return assessmentRepository.listQuestionSets(filters);
    }

    @Override
    public int deleteQuestionSetQuestion(String questionSetGooruOId, String gooruOQuestionId, User caller) {
        QuestionSetQuestionAssoc questionSetQuestionAssoc = new QuestionSetQuestionAssoc();
        questionSetQuestionAssoc.setQuestionSet(getQuestionSet(questionSetGooruOId));
        questionSetQuestionAssoc.setQuestion(getQuestion(gooruOQuestionId));
        questionSetQuestionAssoc = (QuestionSetQuestionAssoc) assessmentRepository
                .getModel(QuestionSetQuestionAssoc.class, questionSetQuestionAssoc);
        if (questionSetQuestionAssoc != null) {
            assessmentRepository.deleteQuestionSetQuestion(questionSetQuestionAssoc);
            return 1;
        } else {
            return 0;
        }
    }

    @Override
    public int deleteQuestionSet(String gooruOQuestionSetId, User caller) {
        QuestionSet questionSet = getQuestionSet(gooruOQuestionSetId);
        if (questionSet != null) {
            assessmentRepository.remove(QuestionSet.class, questionSet.getContentId());
            return 1;
        }
        return 0;
    }

    @Override
    public QuestionSetQuestionAssoc createQuestionSetQuestion(QuestionSetQuestionAssoc questionSetQuestion) {
        assessmentRepository.saveAndFlush(questionSetQuestion);
        return questionSetQuestion;
    }

    @Override
    public List<AssessmentQuestion> getAssessmentQuestions(String gooruOAssessmentId) {
        return assessmentRepository.getAssessmentQuestions(gooruOAssessmentId);
    }

    @Override
    public AssessmentQuestionAssetAssoc uploadQuestionAsset(String gooruQuestionId,
            AssessmentQuestionAssetAssoc questionAsset, boolean index) throws Exception {

        if (questionAsset.getAsset().getFileData() != null && questionAsset.getAsset().getFileData().length > 2) {
            AssessmentQuestion question = getQuestion(gooruQuestionId);
            Asset asset = questionAsset.getAsset();
            asset.setHasUniqueName(true);

            assessmentRepository.save(asset);

            String realPath = asset.getOrganization().getNfsStorageArea().getInternalPath() + question.getFolder();
            this.getResourceImageUtil().sendMsgToGenerateThumbnails(question, asset.getName());
            this.assetManager.saveAssetResource(asset, realPath);

            s3ResourceApiHandler.uploadResourceFileWithNewSession(question, asset.getName());

            if (index) {
                indexHandler.setReIndexRequest(question.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false,
                        false);
            }

            assessmentRepository.save(asset);

            assessmentRepository.saveAndFlush(questionAsset);

            return questionAsset;
        }
        return null;
    }

    @Override
    public AssessmentQuestionAssetAssoc getQuestionAsset(final String assetKey, String gooruOAssessmentId) {
        return assessmentRepository.getQuestionAsset(assetKey, gooruOAssessmentId);
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public AssessmentQuestion copyAssessmentQuestion(User user, String gooruQuestionId) throws Exception {
        AssessmentQuestion question = getQuestion(gooruQuestionId);
        AssessmentQuestion copyQuestion = new AssessmentQuestion();
        if (question != null) {
            copyQuestion.setDescription(question.getDescription());
            copyQuestion.setContentType(question.getContentType());
            copyQuestion.setConcept(question.getConcept());
            copyQuestion.setLicense(question.getLicense());
            copyQuestion.setCopiedResourceId(question.getAssessmentGooruId());
            copyQuestion.setLabel(question.getLabel());
            copyQuestion.setTitle(question.getTitle());
            copyQuestion.setResourceType(question.getResourceType());
            copyQuestion.setSharing(question.getSharing());
            copyQuestion.setTimeToCompleteInSecs(question.getTimeToCompleteInSecs());
            copyQuestion.setDifficultyLevel(question.getDifficultyLevel());
            copyQuestion.setQuestionText(question.getQuestionText());
            copyQuestion.setExplanation(question.getExplanation());
            copyQuestion.setHelpContentLink(question.getHelpContentLink());
            copyQuestion.setInstruction(question.getInstruction());
            copyQuestion.setScorePoints(question.getScorePoints());
            copyQuestion.setUser(user);
            copyQuestion.setCreator(question.getCreator());
            copyQuestion.setType(question.getType());
            if (question.getHints() != null) {
                Set<AssessmentHint> copyHints = new TreeSet<AssessmentHint>();
                for (AssessmentHint hint : question.getHints()) {
                    AssessmentHint copyHint = new AssessmentHint();
                    copyHint.setHintText(hint.getHintText());
                    copyHint.setSequence(hint.getSequence());
                    copyHints.add(copyHint);
                }
                copyQuestion.setHints(copyHints);
            }
            if (question.getAnswers() != null) {
                Set<AssessmentAnswer> copyAnswers = new TreeSet<AssessmentAnswer>();
                for (AssessmentAnswer answer : question.getAnswers()) {
                    AssessmentAnswer copyAnswer = new AssessmentAnswer();
                    copyAnswer.setAnswerText(answer.getAnswerText());
                    copyAnswer.setSequence(answer.getSequence());
                    copyAnswer.setIsCorrect(answer.getIsCorrect());
                    copyAnswer.setMatchingAnswer(answer.getMatchingAnswer());
                    copyAnswer.setUnit(answer.getUnit());
                    copyAnswers.add(copyAnswer);
                }
                copyQuestion.setAnswers(copyAnswers);
            }
            createQuestion(copyQuestion, true);
            if (question.getAssets() != null && question.getAssets().size() > 0) {
                Set<AssessmentQuestionAssetAssoc> questionAssets = new HashSet<AssessmentQuestionAssetAssoc>();
                for (AssessmentQuestionAssetAssoc questionAssetAssoc : question.getAssets()) {
                    AssessmentQuestionAssetAssoc copyQuestionAssetAssoc = new AssessmentQuestionAssetAssoc();
                    Asset asset = new Asset();
                    asset.setDescription(questionAssetAssoc.getAsset().getDescription());
                    asset.setName(questionAssetAssoc.getAsset().getName());
                    asset.setHasUniqueName(questionAssetAssoc.getAsset().getHasUniqueName());
                    assessmentRepository.save(asset);
                    copyQuestionAssetAssoc.setAsset(asset);
                    copyQuestionAssetAssoc.setAssetKey(questionAssetAssoc.getAssetKey());
                    copyQuestion.setThumbnail(questionAssetAssoc.getAsset().getName());
                    copyQuestionAssetAssoc.setQuestion(copyQuestion);
                    questionAssets.add(copyQuestionAssetAssoc);
                    assessmentRepository.save(copyQuestionAssetAssoc);
                }
                assessmentRepository.save(copyQuestion);
                if (copyQuestion.isQuestionNewGen()) {
                    mongoQuestionsService.copyQuestion(gooruQuestionId, copyQuestion.getGooruOid());
                }
                copyQuestion.setAssets(questionAssets);
            }
            StringBuilder sourceFilepath = new StringBuilder(
                    question.getOrganization().getNfsStorageArea().getInternalPath());
            sourceFilepath.append(question.getFolder()).append(File.separator);
            StringBuilder targetFilepath = new StringBuilder(
                    copyQuestion.getOrganization().getNfsStorageArea().getInternalPath());
            targetFilepath.append(copyQuestion.getFolder()).append(File.separator);
            this.getAsyncExecutor().copyResourceFolder(sourceFilepath.toString(), targetFilepath.toString());

        }
        return copyQuestion;
    }

    public ContentRepository getContentRepository() {
        return contentRepository;
    }

    public void setContentRepository(ContentRepository contentRepository) {
        this.contentRepository = contentRepository;
    }

    public BaseRepository getBaseRepository() {
        return baseRepository;
    }

    public void setBaseRepository(BaseRepository baseRepository) {
        this.baseRepository = baseRepository;
    }

    public UserRepository getUserRepository() {
        return userRepository;
    }

    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public boolean assignAsset(String questionGooruOid, Integer assetId, String assetKey) {
        AssessmentQuestionAssetAssoc questionAssetAssoc = assessmentRepository.findQuestionAsset(questionGooruOid,
                assetId);
        if (questionAssetAssoc != null) {
            questionAssetAssoc.setAssetKey(assetKey);
            assessmentRepository.save(questionAssetAssoc);
            return true;
        }
        return false;
    }

    public ResourceManager getResourceManager() {
        return resourceManager;
    }

    public void setResourceManager(ResourceManager resourceManager) {
        this.resourceManager = resourceManager;
    }

    @Override
    public String updateQuizQuestionImage(String gooruContentId, String fileName, Resource resource,
            String assetKey) throws Exception {
        if (fileName != null && ResourceImageUtil.getYoutubeVideoId(fileName) != null
                || fileName.contains(YOUTUBE_URL)) {
            return fileName;
        } else {
            final String mediaFolderPath = resource.getOrganization().getNfsStorageArea().getInternalPath()
                    + Constants.UPLOADED_MEDIA_FOLDER;
            String resourceImageFile = mediaFolderPath + "/" + fileName;
            String newImageFile = mediaFolderPath + "/" + assetKey + "_" + fileName;
            File mediaImage = new File(resourceImageFile);
            File newImage = new File(newImageFile);
            mediaImage.renameTo(newImage);
            fileName = newImage.getName();
            return newImageFile;
        }
    }

    @Override
    public AssessmentQuestion updateQuestionAssest(String gooruQuestionId, String fileNames) throws Exception {
        AssessmentQuestion question = getQuestion(gooruQuestionId);
        final String repositoryPath = question.getOrganization().getNfsStorageArea().getInternalPath();
        final String mediaFolderPath = repositoryPath + "/" + Constants.UPLOADED_MEDIA_FOLDER;
        String[] assetKeyArr = fileNames.split("\\s*,\\s*");
        for (int i = 0; i < assetKeyArr.length; i++) {
            String resourceImageFile = mediaFolderPath + "/" + assetKeyArr[i];
            File mediaImage = new File(resourceImageFile);
            if (!mediaImage.isFile()) {
                throw new BadRequestException("file not found");
            }
            String assetKey = StringUtils.left(assetKeyArr[i], assetKeyArr[i].indexOf("_"));
            String fileName = assetKeyArr[i].split("_")[1];
            byte[] fileContent = FileUtils.readFileToByteArray(mediaImage);
            if (fileContent.length > 0) {
                AssessmentQuestionAssetAssoc questionAsset = null;
                if (assetKey != null && assetKey.length() > 0) {
                    questionAsset = getQuestionAsset(assetKey, gooruQuestionId);
                }
                Asset asset = null;
                if (questionAsset == null) {
                    asset = new Asset();
                    asset.setHasUniqueName(true);
                    questionAsset = new AssessmentQuestionAssetAssoc();
                    questionAsset.setQuestion(question);
                    questionAsset.setAsset(asset);
                    questionAsset.setAssetKey(assetKey);
                } else {
                    asset = questionAsset.getAsset();
                }
                asset.setFileData(fileContent);
                asset.setName(fileName);
                question.setThumbnail(fileName);
                this.getBaseRepository().save(question);
                Set<AssessmentQuestionAssetAssoc> assets = new HashSet<AssessmentQuestionAssetAssoc>();
                assets.add(uploadQuestionAsset(gooruQuestionId, questionAsset, true));
                question.setAssets(assets);
                mediaImage.delete();
            }
        }
        indexHandler.setReIndexRequest(question.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false);
        return question;
    }

    @Override
    public AssessmentQuestion updateQuestionVideoAssest(String gooruQuestionId, String assetKeys) throws Exception {
        AssessmentQuestion question = getQuestion(gooruQuestionId);
        String[] assetKeyArr = assetKeys.split("\\s*,\\s*");
        for (int i = 0; i < assetKeyArr.length; i++) {
            String assetKey = assetKeyArr[i];
            // String fileName = assetKeyArr[i].split("_")[0];
            if (resourceImageUtil.getYoutubeVideoId(assetKey) != null || assetKey.contains(YOUTUBE_URL)) {
                AssessmentQuestionAssetAssoc questionAsset = null;
                if (assetKey != null && assetKey.length() > 0) {
                    questionAsset = getQuestionAsset(assetKey, gooruQuestionId);
                }
                Asset asset = null;
                if (questionAsset == null) {
                    asset = new Asset();
                    asset.setHasUniqueName(true);
                    questionAsset = new AssessmentQuestionAssetAssoc();
                    questionAsset.setQuestion(question);
                    questionAsset.setAsset(asset);
                    questionAsset.setAssetKey(assetKey);
                } else {
                    asset = questionAsset.getAsset();
                }
                asset.setName(assetKey);
                asset.setUrl(assetKey);
                assessmentRepository.save(asset);

                assessmentRepository.saveAndFlush(questionAsset);

                Set<AssessmentQuestionAssetAssoc> assets = new HashSet<AssessmentQuestionAssetAssoc>();
                assets.add(questionAsset);
                question.setAssets(assets);

            }
        }
        indexHandler.setReIndexRequest(question.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false);
        return question;
    }

    @Override
    public void deleteQuestionAssest(String gooruQuestionId) throws Exception {
        this.assessmentRepository.deleteQuestionAssoc(gooruQuestionId);
    }

    @Override
    public void deleteQuizBulk(String gooruContentIds) {
        List<Resource> quizResources = resourceRepository.findAllResourcesByGooruOId(gooruContentIds);
        List<Resource> removeQuizList = new ArrayList<Resource>();
        if (quizResources.size() > 0) {
            String removeContentIds = "";
            int count = 0;
            for (Resource resource : quizResources) {
                if (count > 0) {
                    removeContentIds += ",";
                }
                if (resource.getResourceType().getName().equals(ResourceType.Type.ASSESSMENT_EXAM.getType())
                        || resource.getResourceType().getName()
                                .equals(ResourceType.Type.ASSESSMENT_QUIZ.getType())) {
                    removeContentIds += resource.getGooruOid();
                    removeQuizList.add(resource);
                    count++;
                }
            }
            if (removeQuizList.size() > 0) {
                this.baseRepository.removeAll(removeQuizList);
                indexHandler.setReIndexRequest(removeContentIds, IndexProcessor.DELETE, QUIZ, null, false, false);
            }
        }
    }

    @Override
    public void deleteQuestionBulk(String gooruQuestionIds) {
        List<Resource> questionResources = resourceRepository.findAllResourcesByGooruOId(gooruQuestionIds);
        List<Resource> removeQuestionList = new ArrayList<Resource>();
        if (questionResources.size() > 0) {
            String removeContentIds = "";
            int count = 0;
            for (Resource resource : questionResources) {
                if (count > 0) {
                    removeContentIds += ",";
                }
                if (resource.getResourceType().getName().equals(ResourceType.Type.ASSESSMENT_QUESTION.getType())) {
                    removeContentIds += resource.getGooruOid();
                    removeQuestionList.add(resource);
                    count++;
                }
            }
            if (removeQuestionList.size() > 0) {
                this.baseRepository.removeAll(removeQuestionList);
                indexHandler.setReIndexRequest(removeContentIds, IndexProcessor.INDEX, RESOURCE, null, false,
                        false);
            }
        }
    }

    @Override
    public AssessmentQuestion buildQuestionFromInputParameters(String jsonData, User user, boolean addFlag) {

        XStream xstream = new XStream(new JettisonMappedXmlDriver());
        xstream.alias(QUESTION, AssessmentQuestion.class);
        xstream.alias(ANSWER, AssessmentAnswer.class);
        xstream.alias(HINT, AssessmentHint.class);
        xstream.alias(TAXONOMY_CODE, Code.class);
        xstream.alias(_DEPTH_OF_KNOWLEDGE, ContentMetaDTO.class);
        xstream.alias(_EDUCATIONAL_USE, ContentMetaDTO.class);
        xstream.addImplicitCollection(AssessmentQuestion.class, "deletedMediaFiles", String.class);
        xstream.addImplicitCollection(AssessmentQuestion.class, "mediaFiles", String.class);
        xstream.addImplicitCollection(AssessmentQuestion.class, "depthOfKnowledgeIds", Integer.class);
        xstream.addImplicitCollection(AssessmentQuestion.class, "standardIds", Integer.class);
        xstream.addImplicitCollection(AssessmentQuestion.class, "skillIds", Integer.class);

        /*
         * The change to make sure that if we add some other attributes
         * tomorrow, or as we have added today, we don't have to make them parse
         * in JAVA as they can directly be transferred to JSON store
         */
        xstream.ignoreUnknownElements();
        AssessmentQuestion question = null;
        try {
            question = (AssessmentQuestion) xstream.fromXML(jsonData);
        } catch (Exception e) {
            throw new BadRequestException(e.getCause() != null ? e.getCause().getMessage() : e.getMessage());
        }
        if (addFlag) {
            question.setUser(user);
        }
        if (question.isQuestionNewGen()) {
            question.setAnswers(null);
            question.setHints(null);
        } else {
            if (question.getAnswers() != null) {
                question.setAnswers(new TreeSet<AssessmentAnswer>(question.getAnswers()));
            }
            if (question.getHints() != null) {
                question.setHints(new TreeSet<AssessmentHint>(question.getHints()));
            }
        }

        return question;
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int deleteQuestion(String gooruOQuestionId, User caller) {
        AssessmentQuestion question = getQuestion(gooruOQuestionId);
        if (question != null) {
            assessmentRepository.remove(AssessmentQuestion.class, question.getContentId());
            indexHandler.setReIndexRequest(question.getGooruOid(), IndexProcessor.DELETE, RESOURCE, null, false,
                    false);
            return 1;
        }
        return 0;
    }

    @Override
    public String findAssessmentNameByGooruOId(String gooruOId) {
        return assessmentRepository.findAssessmentNameByGooruOid(gooruOId);
    }

    public ResourceImageUtil getResourceImageUtil() {
        return resourceImageUtil;
    }

    public AsyncExecutor getAsyncExecutor() {
        return asyncExecutor;
    }

    public CustomTableRepository getCustomTableRepository() {
        return customTableRepository;
    }

}