org.sakaiproject.tool.assessment.services.assessment.AssessmentService Maven / Gradle / Ivy
/**********************************************************************************
* $URL$
* $Id$
***********************************************************************************
*
* Copyright (c) 2004, 2005, 2006, 2007, 2008 The Sakai Foundation
*
* Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.
*
**********************************************************************************/
package org.sakaiproject.tool.assessment.services.assessment;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.sakaiproject.authz.api.SecurityAdvisor;
import org.sakaiproject.authz.api.SecurityService;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.content.api.ContentHostingService;
import org.sakaiproject.content.api.ContentResource;
import org.sakaiproject.event.cover.EventTrackingService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.InUseException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.exception.TypeException;
import org.sakaiproject.samigo.util.SamigoConstants;
import org.sakaiproject.tool.assessment.data.dao.assessment.AssessmentData;
import org.sakaiproject.tool.assessment.data.dao.assessment.AssessmentTemplateData;
import org.sakaiproject.tool.assessment.data.dao.assessment.AttachmentData;
import org.sakaiproject.tool.assessment.data.dao.assessment.ItemData;
import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedAssessmentData;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AnswerIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentAttachmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentBaseIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AttachmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemAttachmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemDataIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemMetaDataIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemTextAttachmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemTextIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.SectionAttachmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.SectionDataIfc;
import org.sakaiproject.tool.assessment.data.ifc.shared.TypeIfc;
import org.sakaiproject.tool.assessment.entity.api.CoreAssessmentEntityProvider;
import org.sakaiproject.tool.assessment.entity.api.PublishedAssessmentEntityProvider;
import org.sakaiproject.tool.assessment.facade.AgentFacade;
import org.sakaiproject.tool.assessment.facade.AssessmentFacade;
import org.sakaiproject.tool.assessment.facade.AssessmentFacadeQueriesAPI;
import org.sakaiproject.tool.assessment.facade.AssessmentTemplateFacade;
import org.sakaiproject.tool.assessment.facade.ItemFacade;
import org.sakaiproject.tool.assessment.facade.PublishedAssessmentFacade;
import org.sakaiproject.tool.assessment.facade.PublishedAssessmentFacadeQueries;
import org.sakaiproject.tool.assessment.facade.SectionFacade;
import org.sakaiproject.tool.assessment.facade.TypeFacade;
import org.sakaiproject.tool.assessment.services.ItemService;
import org.sakaiproject.tool.assessment.services.PersistenceService;
import org.sakaiproject.tool.assessment.services.QuestionPoolService;
import org.sakaiproject.tool.cover.ToolManager;
/**
* The AssessmentService calls the service locator to reach the manager on the
* back end.
*
* @author Rachel Gollub
*/
@Slf4j
public class AssessmentService {
public static final int UPDATE_SUCCESS = 0;
public static final int UPDATE_ERROR_DRAW_SIZE_TOO_LARGE = 1;
private SecurityService securityService = ComponentManager.get(SecurityService.class);
// versioning title string that it will look for/use, followed by a number
private static final String VERSION_START = " - ";
/**
* Creates a new QuestionPoolService object.
*/
public AssessmentService() {
}
public AssessmentTemplateFacade getAssessmentTemplate(
String assessmentTemplateId) {
try {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries().getAssessmentTemplate(
new Long(assessmentTemplateId));
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public AssessmentFacade getAssessment(String assessmentId) {
try {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries().getAssessment(
Long.valueOf(assessmentId));
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public AssessmentIfc getAssessment(Long assessmentId) {
try {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries().getAssessment(assessmentId);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public AssessmentFacade getBasicInfoOfAnAssessment(String assessmentId) {
try {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries().getBasicInfoOfAnAssessment(
new Long(assessmentId));
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public AssessmentFacade getBasicInfoOfAnAssessmentFromSectionId(Long sectionId) {
try {
return PersistenceService.getInstance().getAssessmentFacadeQueries().getBasicInfoOfAnAssessmentFromSectionId(sectionId);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public List getAllAssessmentTemplates() {
try {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries().getAllAssessmentTemplates();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public List getAllActiveAssessmentTemplates() {
try {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries()
.getAllActiveAssessmentTemplates();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public List getTitleOfAllActiveAssessmentTemplates() {
try {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries()
.getTitleOfAllActiveAssessmentTemplates();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public List getAllAssessments(String orderBy) {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getAllAssessments(orderBy); // signalling all & no paging
}
public List getAllActiveAssessments(String orderBy) {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getAllActiveAssessments(orderBy); // signalling all & no
// paging
}
/**
* @param orderBy
* @return an ArrayList of AssessmentFacade. It is IMPORTANT to note that
* the object is a partial object which contains no SectionFacade
*/
public List getSettingsOfAllActiveAssessments(String orderBy) {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getSettingsOfAllActiveAssessments(orderBy); // signalling
// all & no
// paging
}
/**
* @param orderBy
* @return an ArrayList of AssessmentFacade. It is IMPORTANT to note that
* the object is a partial object which contains only Assessment
* basic info such as title, lastModifiedDate. This method is used
* by Authoring Front Door
*/
public List getBasicInfoOfAllActiveAssessments(String orderBy,
boolean ascending) {
String siteAgentId = AgentFacade.getCurrentSiteId();
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getBasicInfoOfAllActiveAssessmentsByAgent(orderBy,
siteAgentId, ascending); // signalling all & no
// paging
}
public List getBasicInfoOfAllActiveAssessments(String orderBy) {
String siteAgentId = AgentFacade.getCurrentSiteId();
return PersistenceService
.getInstance()
.getAssessmentFacadeQueries()
.getBasicInfoOfAllActiveAssessmentsByAgent(orderBy, siteAgentId); // signalling
// all
// & no
// paging
}
public List getAllAssessments(int pageSize, int pageNumber,
String orderBy) {
try {
if (pageSize > 0 && pageNumber > 0) {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries().getAllAssessments(
pageSize, pageNumber, orderBy);
} else {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries()
.getAllAssessments(orderBy);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public AssessmentFacade createAssessment(String title, String description,
String typeId, String templateId) throws Exception {
return createAssessment(title, description, typeId, templateId, null);
}
public AssessmentFacade createAssessment(String title, String description,
String typeId, String templateId, String siteId) throws Exception {
AssessmentFacade assessment = null;
try {
AssessmentTemplateFacade assessmentTemplate = null;
// #1 - check templateId and prepared it in Long
Long templateIdLong = AssessmentTemplateFacade.DEFAULTTEMPLATE;
if (StringUtils.isNotBlank(templateId)) {
templateIdLong = new Long(templateId);
}
// #2 - check typeId and prepared it in Long
Long typeIdLong = TypeFacade.HOMEWORK;
if (StringUtils.isNotBlank(typeId)) {
typeIdLong = new Long(typeId);
}
AssessmentFacadeQueriesAPI queries = PersistenceService
.getInstance().getAssessmentFacadeQueries();
log.debug("**** AssessmentFacadeQueries=" + queries);
assessment = queries.createAssessment(title, description,
typeIdLong, templateIdLong, siteId);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new Exception(e);
}
return assessment;
}
public int getQuestionSize(String assessmentId) {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getQuestionSize(new Long(assessmentId));
}
public List getQuestionsIdList(long assessmentId) {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getQuestionsIdList(assessmentId);
}
public void update(AssessmentFacade assessment) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.saveOrUpdate(assessment);
}
public void save(AssessmentTemplateData template) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.saveOrUpdate(template);
}
public void deleteAllSecuredIP(AssessmentIfc assessment) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.deleteAllSecuredIP(assessment);
}
public void saveAssessment(AssessmentFacade assessment) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.saveOrUpdate(assessment);
}
public void deleteAssessmentTemplate(Long assessmentId) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.deleteTemplate(assessmentId);
}
public void removeAssessment(String assessmentId) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.removeAssessment(new Long(assessmentId));
}
/**
* public int checkDelete(long assessmentId){ return
* assessmentService.checkDelete(assessmentId); }
*
* public void deleteAssessment(Id assessmentId) throws
* osid.assessment.AssessmentException {
* assessmentService.deleteAssessment(assessmentId); }
*
* public AssessmentIterator getAssessments() throws
* osid.assessment.AssessmentException { return
* assessmentService.getAssessments(); }
*
*/
public SectionFacade addSection(String assessmentId) {
SectionFacade section = null;
try {
Long assessmentIdLong = new Long(assessmentId);
AssessmentFacadeQueriesAPI queries = PersistenceService
.getInstance().getAssessmentFacadeQueries();
section = queries.addSection(assessmentIdLong);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return section;
}
public void removeSection(String sectionId) {
try {
Long sectionIdLong = new Long(sectionId);
AssessmentFacadeQueriesAPI queries = PersistenceService
.getInstance().getAssessmentFacadeQueries();
queries.removeSection(sectionIdLong);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
public SectionFacade getSection(String sectionId) {
try {
return PersistenceService.getInstance()
.getAssessmentFacadeQueries().getSection(
new Long(sectionId));
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public void saveOrUpdateSection(SectionFacade section) {
try {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.saveOrUpdateSection(section);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public void moveAllItems(String sourceSectionId, String destSectionId) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.moveAllItems(new Long(sourceSectionId),
new Long(destSectionId)); // signalling all & no
// paging
}
public void removeAllItems(String sourceSectionId) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.removeAllItems(new Long(sourceSectionId));
}
public boolean verifyItemsDrawSize(SectionFacade section){
if (section != null && section.getSectionMetaDataByLabel(SectionDataIfc.AUTHOR_TYPE) != null
&& StringUtils.equals(section.getSectionMetaDataByLabel(SectionDataIfc.AUTHOR_TYPE), SectionDataIfc.RANDOM_DRAW_FROM_QUESTIONPOOL.toString())) {
QuestionPoolService qpService = new QuestionPoolService();
List itemlist = qpService
.getAllItems(Long.valueOf(section
.getSectionMetaDataByLabel(SectionDataIfc.POOLID_FOR_RANDOM_DRAW)));
return verifyItemsDrawSize(itemlist.size(), section.getSectionMetaDataByLabel(SectionDataIfc.NUM_QUESTIONS_DRAWN));
}else{
return true;
}
}
private boolean verifyItemsDrawSize(int itemcount, String numberDrawn){
try{
int numberDrawnInt = Integer.parseInt(numberDrawn);
if(numberDrawnInt <=0 || numberDrawnInt>itemcount){
return false;
}
} catch(NumberFormatException e){
return false;
}
return true;
}
public int updateRandomPoolQuestions(SectionFacade section){
return updateRandomPoolQuestions(section, false);
}
public int updateRandomPoolQuestions(SectionFacade section, boolean publishing){
if (section != null && section.getSectionMetaDataByLabel(SectionDataIfc.AUTHOR_TYPE) != null
&& StringUtils.equals(section.getSectionMetaDataByLabel(SectionDataIfc.AUTHOR_TYPE), SectionDataIfc.RANDOM_DRAW_FROM_QUESTIONPOOL.toString())) {
QuestionPoolService qpService = new QuestionPoolService();
List itemlist = qpService.getAllItems(Long.valueOf(section
.getSectionMetaDataByLabel(SectionDataIfc.POOLID_FOR_RANDOM_DRAW)));
if(verifyItemsDrawSize(itemlist.size(), section.getSectionMetaDataByLabel(SectionDataIfc.NUM_QUESTIONS_DRAWN))){
// random section:
removeAllItems(section.getSectionId().toString());
ItemService itemService = new ItemService();
String agentId = AgentFacade.getAgentString();
Iterator itemIter = section.getItemSet().iterator();
while (itemIter.hasNext()) {
ItemDataIfc item = (ItemDataIfc) itemIter.next();
List poolIds = qpService.getPoolIdsByItem(item.getItemId());
if (poolIds.isEmpty()) {
Long deleteId = item.getItemId();
itemService.deleteItem(deleteId, agentId);
EventTrackingService.post(EventTrackingService.newEvent(SamigoConstants.EVENT_ASSESSMENT_ITEM_DELETE, "/sam/" +AgentFacade.getCurrentSiteId() + "/removed itemId=" + deleteId, true));
itemIter.remove();
}
}
// need to reload
section = getSection(section.getSectionId().toString());
// ItemService itemservice = new ItemService();
boolean hasRandomPartScore = false;
Double score = null;
String requestedScore = (section.getSectionMetaDataByLabel(SectionDataIfc.POINT_VALUE_FOR_QUESTION) != null) ?
section.getSectionMetaDataByLabel(SectionDataIfc.POINT_VALUE_FOR_QUESTION) : "";
if (StringUtils.isNotBlank(requestedScore)) {
hasRandomPartScore = true;
score = new Double(requestedScore);
}
boolean hasRandomPartDiscount = false;
Double discount = null;
String requestedDiscount = (section.getSectionMetaDataByLabel(SectionDataIfc.DISCOUNT_VALUE_FOR_QUESTION) != null) ?
section.getSectionMetaDataByLabel(SectionDataIfc.DISCOUNT_VALUE_FOR_QUESTION) : "";
if (StringUtils.isNotBlank(requestedDiscount)) {
hasRandomPartDiscount = true;
discount = new Double(requestedDiscount);
}
int i = 0;
Iterator iter = itemlist.iterator();
while (iter.hasNext()) {
ItemFacade item = (ItemFacade) iter.next();
// copy item so we can have it in more than one assessment
item = qpService.copyItemFacade2(item);
item.setSection(section);
item.setSequence(Integer.valueOf(i + 1));
// if (hasRandomPartScore || hasRandomPartDiscount) {
if (hasRandomPartScore)
item.setScore(score);
long itemTypeId = item.getTypeId().longValue();
String mcmsPartialCredit = item.getItemMetaDataByLabel(ItemMetaDataIfc.MCMS_PARTIAL_CREDIT);
if (hasRandomPartDiscount &&
(itemTypeId == TypeFacade.MULTIPLE_CHOICE.longValue() ||
itemTypeId == TypeFacade.TRUE_FALSE.longValue() ||
itemTypeId == TypeFacade.MULTIPLE_CORRECT_SINGLE_SELECTION.longValue() ||
(itemTypeId == TypeFacade.MULTIPLE_CORRECT.longValue() && "false".equals(mcmsPartialCredit))))
item.setDiscount(discount);
ItemDataIfc data = item.getData();
Set itemTextSet = data.getItemTextSet();
if (itemTextSet != null) {
Iterator iterITS = itemTextSet.iterator();
while (iterITS.hasNext()) {
ItemTextIfc itemText = (ItemTextIfc) iterITS.next();
if(publishing){
itemText.setText(copyContentHostingAttachments(itemText.getText(), AgentFacade.getCurrentSiteId()));
}
Set answerSet = itemText.getAnswerSet();
if (answerSet != null) {
Iterator iterAS = answerSet.iterator();
while (iterAS.hasNext()) {
AnswerIfc answer = (AnswerIfc) iterAS
.next();
if(publishing){
answer.setText(copyContentHostingAttachments(answer.getText(), AgentFacade.getCurrentSiteId()));
}
if (hasRandomPartScore)
answer.setScore(score);
if (hasRandomPartDiscount &&
(itemTypeId == TypeFacade.MULTIPLE_CHOICE.longValue() ||
itemTypeId == TypeFacade.TRUE_FALSE.longValue() ||
itemTypeId == TypeFacade.MULTIPLE_CORRECT_SINGLE_SELECTION.longValue() ||
(itemTypeId == TypeFacade.MULTIPLE_CORRECT.longValue() && "false".equals(mcmsPartialCredit))))
answer.setDiscount(discount);
}
}
}
}
// }
section.addItem(item);
EventTrackingService.post(EventTrackingService.newEvent(SamigoConstants.EVENT_ASSESSMENT_SAVEITEM, "/sam/" + AgentFacade.getCurrentSiteId() + "/saved itemId=" + item.getItemId().toString(), true));
i = i + 1;
}
//update meta data for date:
//We need this in a standard format so it can be parsed later. This is ISO8601 format -DH
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZ");
section.addSectionMetaData(SectionDataIfc.QUESTIONS_RANDOM_DRAW_DATE, df.format(new Date()));
saveOrUpdateSection(section);
}else{
return UPDATE_ERROR_DRAW_SIZE_TOO_LARGE;
}
}
return UPDATE_SUCCESS;
}
public int updateAllRandomPoolQuestions(AssessmentFacade assessment){
return updateAllRandomPoolQuestions(assessment, false);
}
public int updateAllRandomPoolQuestions(AssessmentFacade assessment, boolean publishing){
//verify that we can update the sections first:
for(SectionFacade section : (List) assessment.getSectionArray()){
if(!verifyItemsDrawSize(section)){
return UPDATE_ERROR_DRAW_SIZE_TOO_LARGE;
}
}
//passed all tests, so update pool questions:
for(SectionFacade section : (List) assessment.getSectionArray()){
updateRandomPoolQuestions(section, publishing);
}
return UPDATE_SUCCESS;
}
public List getBasicInfoOfAllActiveAssessmentTemplates(String orderBy) {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getBasicInfoOfAllActiveAssessmentTemplates(orderBy); // signalling
// all &
// no
// paging
}
public AssessmentFacade createAssessmentWithoutDefaultSection(String title,
String description, String typeId, String templateId) throws Exception {
return createAssessmentWithoutDefaultSection(title, description, typeId, templateId, null);
}
public AssessmentFacade createAssessmentWithoutDefaultSection(String title,
String description, String typeId, String templateId, String siteId) throws Exception {
AssessmentFacade assessment = null;
try {
AssessmentTemplateFacade assessmentTemplate = null;
// #1 - check templateId and prepared it in Long
Long templateIdLong = AssessmentTemplateFacade.DEFAULTTEMPLATE;
if (StringUtils.isNotBlank(templateId)) {
templateIdLong = new Long(templateId);
}
// #2 - check typeId and prepared it in Long
Long typeIdLong = TypeFacade.HOMEWORK;
if (StringUtils.isNotBlank(typeId)) {
typeIdLong = new Long(typeId);
}
AssessmentFacadeQueriesAPI queries = PersistenceService
.getInstance().getAssessmentFacadeQueries();
assessment = queries.createAssessmentWithoutDefaultSection(title,
description, typeIdLong, templateIdLong, siteId);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new Exception(e);
}
return assessment;
}
public boolean assessmentTitleIsUnique(String assessmentBaseId,
String title, boolean isTemplate) {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.assessmentTitleIsUnique(new Long(assessmentBaseId), title,
Boolean.valueOf(isTemplate));
}
public List getAssessmentByTemplate(String templateId) {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getAssessmentByTemplate(new Long(templateId));
}
public List getDefaultMetaDataSet() {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getDefaultMetaDataSet();
}
public void deleteAllMetaData(AssessmentBaseIfc assessment) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.deleteAllMetaData(assessment);
}
public ItemAttachmentIfc createItemAttachment(ItemDataIfc item,
String resourceId, String filename, String protocol) {
return createItemAttachment(item, resourceId,
filename, protocol, true);
}
public ItemAttachmentIfc createItemAttachment(ItemDataIfc item,
String resourceId, String filename, String protocol, boolean isEditPendingAssessmentFlow) {
ItemAttachmentIfc attachment = null;
try {
AssessmentFacadeQueriesAPI queries = PersistenceService
.getInstance().getAssessmentFacadeQueries();
attachment = queries.createItemAttachment(item, resourceId,
filename, protocol, isEditPendingAssessmentFlow);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return attachment;
}
public ItemTextAttachmentIfc createItemTextAttachment(ItemTextIfc itemText,
String resourceId, String filename, String protocol) {
return createItemTextAttachment(itemText, resourceId,
filename, protocol, true);
}
public ItemTextAttachmentIfc createItemTextAttachment(ItemTextIfc itemText,
String resourceId, String filename, String protocol, boolean isEditPendingAssessmentFlow) {
ItemTextAttachmentIfc attachment = null;
try {
AssessmentFacadeQueriesAPI queries = PersistenceService
.getInstance().getAssessmentFacadeQueries();
attachment = queries.createItemTextAttachment(itemText, resourceId,
filename, protocol, isEditPendingAssessmentFlow);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return attachment;
}
public void updateAssessmentLastModifiedInfo(
AssessmentIfc assessment) {
try {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.updateAssessmentLastModifiedInfo((AssessmentFacade) assessment);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public SectionAttachmentIfc createSectionAttachment(SectionDataIfc section,
String resourceId, String filename, String protocol) {
SectionAttachmentIfc attachment = null;
try {
AssessmentFacadeQueriesAPI queries = PersistenceService
.getInstance().getAssessmentFacadeQueries();
attachment = queries.createSectionAttachment(section, resourceId,
filename, protocol);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return attachment;
}
public void removeSectionAttachment(String attachmentId) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.removeSectionAttachment(new Long(attachmentId));
}
public AssessmentAttachmentIfc createAssessmentAttachment(
AssessmentIfc assessment, String resourceId, String filename,
String protocol) {
AssessmentAttachmentIfc attachment = null;
try {
AssessmentFacadeQueriesAPI queries = PersistenceService
.getInstance().getAssessmentFacadeQueries();
attachment = queries.createAssessmentAttachment(assessment,
resourceId, filename, protocol);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return attachment;
}
public void removeAssessmentAttachment(String attachmentId) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.removeAssessmentAttachment(new Long(attachmentId));
}
public AttachmentData createEmailAttachment(String resourceId,
String filename, String protocol) {
AttachmentData attachment = null;
try {
AssessmentFacadeQueriesAPI queries = PersistenceService
.getInstance().getAssessmentFacadeQueries();
attachment = queries.createEmailAttachment(resourceId, filename,
protocol);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return attachment;
}
public List getAssessmentResourceIdList(AssessmentIfc pub) {
List resourceIdList = new ArrayList();
List list = pub.getAssessmentAttachmentList();
if (list != null) {
resourceIdList = getResourceIdList(list);
}
Set sectionSet = pub.getSectionSet();
Iterator iter = sectionSet.iterator();
while (iter.hasNext()) {
SectionDataIfc section = (SectionDataIfc) iter.next();
List sectionAttachments = getSectionResourceIdList(section);
if (sectionAttachments != null) {
resourceIdList.addAll(sectionAttachments);
}
}
log.debug("*** resource size=" + resourceIdList.size());
return resourceIdList;
}
public List getSectionResourceIdList(SectionDataIfc section) {
List resourceIdList = new ArrayList();
List list = section.getSectionAttachmentList();
if (list != null) {
resourceIdList = getResourceIdList(list);
}
Set itemSet = section.getItemSet();
Iterator iter1 = itemSet.iterator();
while (iter1.hasNext()) {
ItemDataIfc item = (ItemDataIfc) iter1.next();
List itemAttachments = getItemResourceIdList(item);
if (itemAttachments != null) {
resourceIdList.addAll(itemAttachments);
}
}
return resourceIdList;
}
public List getItemResourceIdList(ItemDataIfc item) {
List resourceIdList = new ArrayList();
List list = item.getItemAttachmentList();
if (list != null) {
resourceIdList = getResourceIdList(list);
}
return resourceIdList;
}
private List getResourceIdList(List list) {
List resourceIdList = new ArrayList();
for (int i = 0; i < list.size(); i++) {
AttachmentIfc attach = (AttachmentIfc) list.get(i);
resourceIdList.add(attach.getResourceId());
}
return resourceIdList;
}
public void deleteResources(List resourceIdList) {
if (resourceIdList == null)
return;
for (int i = 0; i < resourceIdList.size(); i++) {
String resourceId = (String) resourceIdList.get(i);
resourceId = resourceId.trim();
if (resourceId.toLowerCase().startsWith("/attachment")) {
try {
log.debug("removing=" + resourceId);
AssessmentService.getContentHostingService().removeResource(resourceId);
} catch (PermissionException e) {
log.warn("cannot remove resourceId=" + resourceId + ":"
+ e.getMessage());
log.warn("PermissionException from ContentHostingService:"
+ e.getMessage());
} catch (IdUnusedException e) {
log.warn("cannot remove resourceId=" + resourceId + ":"
+ e.getMessage());
log.warn("IdUnusedException from ContentHostingService:"
+ e.getMessage());
} catch (TypeException e) {
log.warn("cannot remove resourceId=" + resourceId + ":"
+ e.getMessage());
log.warn("TypeException from ContentHostingService:"
+ e.getMessage());
} catch (InUseException e) {
log.warn("cannot remove resourceId=" + resourceId + ":"
+ e.getMessage());
log.warn("InUseException from ContentHostingService:"
+ e.getMessage());
}
}
}
}
public void saveOrUpdateAttachments(List list) {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.saveOrUpdateAttachments(list);
}
public ContentResource createCopyOfContentResource(String resourceId,
String filename, String toContext) {
// trouble using Validator, so use string replacement instead
// java.lang.NoClassDefFoundError: org/sakaiproject/util/Validator
filename = filename.replaceAll("http://","http:__");
ContentResource cr_copy = null;
SecurityAdvisor securityAdvisor = new SecurityAdvisor(){
@Override
public SecurityAdvice isAllowed(String arg0, String arg1,
String arg2) {
if(ContentHostingService.AUTH_RESOURCE_READ.equals(arg1)){
return SecurityAdvice.ALLOWED;
}else{
return SecurityAdvice.PASS;
}
}
};
try {
securityService.pushAdvisor(securityAdvisor);
// create a copy of the resource
ContentResource cr = AssessmentService.getContentHostingService().getResource(resourceId);
String escapedName = escapeResourceName(filename);
if (StringUtils.isNotBlank(toContext)) {
cr_copy = AssessmentService.getContentHostingService().addAttachmentResource(escapedName,
toContext,
ToolManager.getTool("sakai.samigo").getTitle(), cr
.getContentType(), cr.streamContent(), cr.getProperties());
}
else {
cr_copy = AssessmentService.getContentHostingService().addAttachmentResource(escapedName,
ToolManager.getCurrentPlacement().getContext(),
ToolManager.getTool("sakai.samigo").getTitle(), cr
.getContentType(), cr.streamContent(), cr.getProperties());
}
} catch (Exception e) {
log.warn("Could not copy resource " + resourceId + ", " + e.getMessage());
} finally{
securityService.popAdvisor(securityAdvisor);
}
return cr_copy;
}
public ContentResource createCopyOfContentResource(String resourceId,
String filename) {
return createCopyOfContentResource(resourceId, filename, null);
}
/** These characters are not allowed in a resource id */
public static final String INVALID_CHARS_IN_RESOURCE_ID = "^/\\{}[]()%*?#&=\n\r\t\b\f";
protected static final String MAP_TO_A = "?";
protected static final String MAP_TO_B = "§§";
protected static final String MAP_TO_C = "?¢¢";
protected static final String MAP_TO_E = "??¾®®";
protected static final String MAP_TO_I = "";
protected static final String MAP_TO_L = "££";
protected static final String MAP_TO_N = "";
protected static final String MAP_TO_O = "
";
protected static final String MAP_TO_U = "?";
protected static final String MAP_TO_Y = "Ø´??";
protected static final String MAP_TO_X = "???¤©»¨±?«µ¦À?";
/**
* These characters are allowed; but if escapeResourceName() is called, they are escaped (actually, removed) Certain characters cause problems with filenames in certain OSes - so get rid of these characters in filenames
*/
protected static final String ESCAPE_CHARS_IN_RESOURCE_ID = ";'\"";
/**
* Return a string based on id that is valid according to Resource name validity rules.
*
* @param id
* The string to escape.
* @return id fully escaped using Resource name validity rules.
*/
public static String escapeResourceName(String id)
{
if (id == null) return "";
id = id.trim();
try
{
StringBuilder buf = new StringBuilder();
for (int i = 0; i < id.length(); i++)
{
char c = id.charAt(i);
if (MAP_TO_A.indexOf(c) >= 0)
{
buf.append('a');
}
else if (MAP_TO_E.indexOf(c) >= 0)
{
buf.append('e');
}
else if (MAP_TO_I.indexOf(c) >= 0)
{
buf.append('i');
}
else if (MAP_TO_O.indexOf(c) >= 0)
{
buf.append('o');
}
else if (MAP_TO_U.indexOf(c) >= 0)
{
buf.append('u');
}
else if (MAP_TO_Y.indexOf(c) >= 0)
{
buf.append('y');
}
else if (MAP_TO_N.indexOf(c) >= 0)
{
buf.append('n');
}
else if (MAP_TO_B.indexOf(c) >= 0)
{
buf.append('b');
}
else if (MAP_TO_C.indexOf(c) >= 0)
{
buf.append('c');
}
else if (MAP_TO_L.indexOf(c) >= 0)
{
buf.append('l');
}
else if (MAP_TO_X.indexOf(c) >= 0)
{
buf.append('x');
}
else if (c < '\040') // Remove any ascii control characters
{
buf.append('_');
}
else if (INVALID_CHARS_IN_RESOURCE_ID.indexOf(c) >= 0 || ESCAPE_CHARS_IN_RESOURCE_ID.indexOf(c) >= 0)
{
buf.append('_');
}
else
{
buf.append(c);
}
}
String rv = buf.toString();
return rv;
}
catch (Exception e)
{
log.warn("escapeResourceName: ", e);
return id;
}
} // escapeResourceName
public void copyAllAssessments(String fromContext, String toContext, MaptransversalMap) {
try {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.copyAllAssessments(fromContext, toContext, transversalMap);
List publist =
PersistenceService.getInstance().getPublishedAssessmentFacadeQueries()
.getBasicInfoOfAllPublishedAssessments(PublishedAssessmentFacadeQueries.DUE, true, fromContext);
for (PublishedAssessmentFacade facade: publist) {
PublishedAssessmentData data = PersistenceService.getInstance().getPublishedAssessmentFacadeQueries().loadPublishedAssessment(facade.getPublishedAssessmentId());
if (data != null) {
String oldRef = PublishedAssessmentEntityProvider.ENTITY_PREFIX + "/" + data.getPublishedAssessmentId();
String oldCore = CoreAssessmentEntityProvider.ENTITY_PREFIX + "/" + data.getAssessmentId();
String newCore = transversalMap.get(oldCore);
if (oldRef != null && newCore != null)
transversalMap.put(oldRef, newCore);
}
}
} catch (Exception e) {
log.error(e.getMessage());
throw new RuntimeException(e);
}
}
public void copyAssessment(String assessmentId, String appendCopyTitle) {
try {
PersistenceService.getInstance().getAssessmentFacadeQueries()
.copyAssessment(assessmentId, appendCopyTitle);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public List getAllActiveAssessmentsbyAgent(String fromContext) {
try {
return PersistenceService.getInstance().getAssessmentFacadeQueries()
.getAllActiveAssessmentsByAgent(fromContext);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
/**
* Get the siteid for the given assesment
* @param assessmentId
* @return
*/
public String getAssessmentSiteId(String assessmentId){
return PersistenceService.getInstance().getAssessmentFacadeQueries().getAssessmentSiteId(assessmentId);
}
public String getAssessmentCreatedBy(String assessmentId){
return PersistenceService.getInstance().getAssessmentFacadeQueries().getAssessmentCreatedBy(assessmentId);
}
public Set copyItemAttachmentSet(ItemData newItem, Set itemAttachmentSet){
return PersistenceService.getInstance().getAssessmentFacadeQueries().copyItemAttachmentSet(newItem, itemAttachmentSet);
}
public static ContentHostingService getContentHostingService(){
return (ContentHostingService) ComponentManager.get(ContentHostingService.class.getName());
}
public List getFavoriteColChoicesbyAgent(String fromContext) {
try {
return PersistenceService.getInstance().getFavoriteColChoicesFacadeQueries()
.getFavoriteColChoicesByAgent(fromContext);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
public String copyContentHostingAttachments(String text, String toContext) {
if(text != null){
ContentResource cr = null;
String[] sources = StringUtils.splitByWholeSeparator(text, "src=\"");
Set attachments = new HashSet();
for (String source : sources) {
String theHref = StringUtils.substringBefore(source, "\"");
if (StringUtils.contains(theHref, "/access/content/")) {
attachments.add(theHref);
}
}
if (attachments.size() > 0) {
log.info("Found " + attachments.size() + " attachments buried in question or answer text");
SecurityAdvisor securityAdvisor = new SecurityAdvisor(){
@Override
public SecurityAdvice isAllowed(String arg0, String arg1,
String arg2) {
if(ContentHostingService.AUTH_RESOURCE_READ.equals(arg1)){
return SecurityAdvice.ALLOWED;
}else{
return SecurityAdvice.PASS;
}
}
};
try{
securityService.pushAdvisor(securityAdvisor);
for (String attachment : attachments) {
String resourceIdOrig = "/" + StringUtils.substringAfter(attachment, "/access/content/");
String resourceId = URLDecoder.decode(resourceIdOrig);
resourceId = resourceId.trim();
String filename = StringUtils.substringAfterLast(attachment, "/");
try {
cr = AssessmentService.getContentHostingService().getResource(resourceId);
} catch (IdUnusedException e) {
log.warn("Could not find resource (" + resourceId + ") that was embedded in a question or answer");
} catch (TypeException e) {
log.warn("TypeException for resource (" + resourceId + ") that was embedded in a question or answer", e);
} catch (PermissionException e) {
log.warn("No permission for resource (" + resourceId + ") that was embedded in a question or answer");
}
if (cr != null && StringUtils.isNotEmpty(filename)) {
ContentResource crCopy = createCopyOfContentResource(cr.getId(), filename, toContext);
text = StringUtils.replace(text, resourceIdOrig, StringUtils.substringAfter(crCopy.getReference(), "/content"));
}
}
}
catch(Exception e){
log.error(e.getMessage());
}
finally{
securityService.popAdvisor(securityAdvisor);
}
}
}
return text;
}
/**
* Exports an assessment to mark up text
*
* @param assessment
* @param bundle
* @return
*/
public String exportAssessmentToMarkupText(AssessmentFacade assessment, Map bundle) {
StringBuilder markupText = new StringBuilder();
int nQuestion = 1;
for (Object sectionObj : assessment.getSectionArray()) {
SectionFacade section = (SectionFacade)sectionObj;
List items = null;
boolean hasRandomPartScore = false;
Double score = null;
boolean hasRandomPartDiscount = false;
Double discount = null;
if (StringUtils.equals(section.getSectionMetaDataByLabel(SectionDataIfc.AUTHOR_TYPE), SectionDataIfc.QUESTIONS_AUTHORED_ONE_BY_ONE.toString()))
{
items = section.getItemArray();
}
else
{
String requestedScore = StringUtils.trimToEmpty(section.getSectionMetaDataByLabel(SectionDataIfc.POINT_VALUE_FOR_QUESTION));
if (StringUtils.isNotEmpty(requestedScore)) {
hasRandomPartScore = true;
try {
score = new Double(requestedScore);
} catch (NumberFormatException e) {
log.error("NumberFormatException converting to Double: " + requestedScore);
}
}
String requestedDiscount = StringUtils.trimToEmpty(section.getSectionMetaDataByLabel(SectionDataIfc.DISCOUNT_VALUE_FOR_QUESTION));
if (StringUtils.isNotEmpty(requestedDiscount)) {
hasRandomPartDiscount = true;
try {
discount = new Double(requestedDiscount);
} catch (NumberFormatException e) {
log.error("NumberFormatException converting to Double: " + requestedDiscount);
}
}
QuestionPoolService qpService = new QuestionPoolService();
try {
Long sectionId = Long.valueOf(section.getSectionMetaDataByLabel(SectionDataIfc.POOLID_FOR_RANDOM_DRAW));
items = qpService.getAllItems(sectionId);
} catch (NumberFormatException e) {
log.error("NumberFormatException converting to Long: " + section.getSectionMetaDataByLabel(SectionDataIfc.POOLID_FOR_RANDOM_DRAW));
}
}
for (ItemDataIfc item : items)
{
// only exports these questions types
if (!isQuestionTypeExportable2MarkupText(item.getTypeId())) {
continue;
}
markupText.append(nQuestion).append(". ");
if (hasRandomPartScore) {
markupText.append("(").append(score).append(" ").append(bundle.get("points")).append(")");
}
else {
markupText.append("(").append(item.getScore()).append(" ").append(bundle.get("points")).append(")");
}
if (hasRandomPartDiscount && discount != null && discount > 0) {
markupText.append(" (").append(discount).append(" ").append(bundle.get("discount")).append(")");
}
else if (!hasRandomPartDiscount && item.getDiscount() != null && item.getDiscount() > 0) {
markupText.append(" (").append(item.getDiscount()).append(" ").append(bundle.get("discount")).append(")");
}
for (ItemTextIfc itemText : item.getItemTextArray()) {
markupText.append("\n");
if (TypeIfc.FILL_IN_BLANK.intValue() == item.getTypeId()
|| TypeIfc.FILL_IN_NUMERIC.intValue() == item.getTypeId()) {
markupText.append(itemText.getText().replaceAll("\\{\\}", ""));
}
else {
markupText.append(itemText.getText());
}
// Answer in Essay question's doesn't need to be exported
if (TypeIfc.ESSAY_QUESTION.intValue() == item.getTypeId()) {
continue;
}
for (AnswerIfc answer : itemText.getAnswerArray()) {
markupText.append("\n");
if (answer.getIsCorrect()) {
markupText.append("*");
}
if (TypeIfc.MULTIPLE_CHOICE.intValue() == item.getTypeId()
|| TypeIfc.MULTIPLE_CORRECT.intValue() == item.getTypeId()) {
markupText.append(answer.getLabel()).append(". ");
}
if (TypeIfc.FILL_IN_NUMERIC.intValue() == item.getTypeId()) {
markupText.append("{").append(answer.getText()).append("}");
}
else if (TypeIfc.TRUE_FALSE.intValue() == item.getTypeId()) {
String boolText = bundle.get("false");
if (Boolean.parseBoolean(answer.getText())) {
boolText = bundle.get("true");
}
markupText.append(boolText);
}
else {
markupText.append(answer.getText());
}
}
}
String randomized = item.getItemMetaDataByLabel(ItemMetaDataIfc.RANDOMIZE);
if (randomized != null && Boolean.valueOf(randomized)) {
markupText.append("\n");
markupText.append(bundle.get("randomize"));
}
if (item.getHasRationale() != null && item.getHasRationale()) {
markupText.append("\n");
markupText.append(bundle.get("rationale"));
}
if (StringUtils.isNotEmpty(item.getCorrectItemFeedback())) {
markupText.append("\n");
markupText.append("#FBOK:").append(item.getCorrectItemFeedback());
}
if (StringUtils.isNotEmpty(item.getInCorrectItemFeedback())) {
markupText.append("\n");
markupText.append("#FBNOK:").append(item.getInCorrectItemFeedback());
}
markupText.append("\n");
nQuestion++;
}
}
return markupText.toString();
}
/**
* Check if there are questions not exportable to markup text
*
* @param assessment
* @return
*/
public boolean isExportable(AssessmentFacade assessment) {
boolean exportToMarkupText = false;
for (Object sectionObj : assessment.getSectionArray()) {
SectionFacade section = (SectionFacade)sectionObj;
List items = null;
if (section != null) {
if (section.getSectionMetaDataByLabel(SectionDataIfc.AUTHOR_TYPE) == null || StringUtils.equals(section.getSectionMetaDataByLabel(SectionDataIfc.AUTHOR_TYPE), SectionDataIfc.QUESTIONS_AUTHORED_ONE_BY_ONE.toString()))
{
items = section.getItemArray();
}
else if (StringUtils.equals(section.getSectionMetaDataByLabel(SectionDataIfc.AUTHOR_TYPE), SectionDataIfc.RANDOM_DRAW_FROM_QUESTIONPOOL.toString()))
{
QuestionPoolService qpService = new QuestionPoolService();
try {
Long qpId = Long.valueOf(section.getSectionMetaDataByLabel(SectionDataIfc.POOLID_FOR_RANDOM_DRAW));
items = qpService.getAllItems(qpId);
} catch (NumberFormatException e) {
log.error("NumberFormatException converting to Long: " + section.getSectionMetaDataByLabel(SectionDataIfc.POOLID_FOR_RANDOM_DRAW));
}
}
}
if (items == null) {
log.info("Items for assessment {} section {} is null in isExportable", assessment.getAssessmentId(), section.getSectionId());
}
else {
for (ItemDataIfc item : items)
{
// only exports these questions types
if (isQuestionTypeExportable2MarkupText(item.getTypeId())) {
exportToMarkupText = true;
break;
}
}
}
if (exportToMarkupText) {
break;
}
}
return exportToMarkupText;
}
/**
* Return true if the item can be exportable to mark up text
*
* @param itemTypeId
* @return
*/
public boolean isQuestionTypeExportable2MarkupText(Long itemTypeId) {
boolean exportable = false;
exportable = exportable || (TypeIfc.MULTIPLE_CHOICE.intValue() == itemTypeId.intValue());
exportable = exportable || (TypeIfc.MULTIPLE_CORRECT.intValue() == itemTypeId.intValue());
exportable = exportable || (TypeIfc.FILL_IN_BLANK.intValue() == itemTypeId.intValue());
exportable = exportable || (TypeIfc.FILL_IN_NUMERIC.intValue() == itemTypeId.intValue());
exportable = exportable || (TypeIfc.TRUE_FALSE.intValue() == itemTypeId.intValue());
exportable = exportable || (TypeIfc.ESSAY_QUESTION.intValue() == itemTypeId.intValue());
return exportable;
}
public static String copyStringAttachment(String stringWithAttachment) {
AssessmentService assessmentService = new AssessmentService();
if(AgentFacade.getCurrentSiteId()!=null){
return assessmentService.copyContentHostingAttachments(stringWithAttachment, AgentFacade.getCurrentSiteId());
}
return stringWithAttachment;
}
public List getDeletedAssessments(String siteId) {
return PersistenceService.getInstance().getAssessmentFacadeQueries().getDeletedAssessments(siteId);
}
public void restoreAssessment(Long assessmentId) {
PersistenceService.getInstance().getAssessmentFacadeQueries().restoreAssessment(assessmentId);
}
/**
* Append " - 2", " - 3", etc. incrementing as you go.
* @param original title
* @return title with versioning
*/
public static String renameDuplicate(String title) {
if (title == null) {
title = "";
}
String rename = "";
int index = title.lastIndexOf(VERSION_START);
// If it is versioned
if (index > -1) {
String mainPart = "";
String versionPart = title.substring(index);
if(index > 0) {
mainPart = title.substring(0, index);
}
int nIndex = index + VERSION_START.length();
String version = title.substring(nIndex);
int versionNumber = 0;
try {
versionNumber = Integer.parseInt(version);
if (versionNumber < 2) {
versionNumber = 2;
}
versionPart = VERSION_START + (versionNumber + 1);
rename = mainPart + versionPart;
} catch (NumberFormatException ex) {
rename = title + VERSION_START + "2";
}
} else {
rename = title + VERSION_START + "2";
}
return rename;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy