Java tutorial
/********************************************************************************** * $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.ui.bean.author; import java.io.Serializable; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.util.ResourceLoader; import org.sakaiproject.content.api.ContentResource; import org.sakaiproject.content.api.FilePickerHelper; import org.sakaiproject.entity.api.Reference; import org.sakaiproject.entity.cover.EntityManager; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.exception.TypeException; import org.sakaiproject.tool.api.ToolSession; import org.sakaiproject.tool.assessment.data.ifc.assessment.AttachmentIfc; import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemTextAttachmentIfc; import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemDataIfc; import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemTextIfc; import org.sakaiproject.tool.assessment.services.ItemService; import org.sakaiproject.tool.assessment.services.PublishedItemService; import org.sakaiproject.tool.assessment.services.assessment.AssessmentService; import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil; import org.sakaiproject.tool.cover.SessionManager; import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import javax.faces.component.UIComponent; import javax.faces.component.UIInput; import javax.faces.context.ExternalContext; import org.sakaiproject.tool.assessment.jsf.convert.AnswerSurveyConverter; @SuppressWarnings("deprecation") public class AnswerBean implements Serializable, Comparable { private static final long serialVersionUID = 7526471155622776147L; private String text; private Long sequence; private String label; private String feedback; private Boolean isCorrect; // for EMI questions private String correctOptionLabels; // for EMI questions private String requiredOptionsCount; //for EMI questions private Double score = new Double(0.0); // Whether the user set the score or it was auto set private Boolean scoreUserSet = Boolean.FALSE; //Attachments for EMI questions private List attachmentList; //for navigation private String outcome; private static Log log = LogFactory.getLog(AnswerBean.class); private String partialCredit = "0"; //to incorporate partial credit private static ResourceLoader rb = new ResourceLoader("org.sakaiproject.tool.assessment.bundle.AuthorMessages"); public static final String choiceLabels = rb.getString("choice_labels"); public AnswerBean() { } public AnswerBean(String ptext, Long pseq, String plabel, String pfdbk, Boolean pcorr, String pgrade, Double pscore) { this.text = ptext; this.sequence = pseq; this.label = plabel; this.feedback = pfdbk; this.isCorrect = pcorr; this.score = pscore; } public String getText() { AnswerSurveyConverter conv = new AnswerSurveyConverter(); return conv.getAsString(null, null, text); } public void setText(String text) { this.text = text; } public Long getSequence() { return sequence; } public void setSequence(Long sequence) { this.sequence = sequence; } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } public String getFeedback() { return feedback; } public void setFeedback(String feedback) { this.feedback = feedback; } public Boolean getIsCorrect() { return isCorrect; } public void setIsCorrect(Boolean isCorrect) { this.isCorrect = isCorrect; } public static String[] getChoiceLabels() { String[] lables = choiceLabels.split(":"); return lables; } public static String[] getChoiceLabels(int labelNum) { String[] lables = choiceLabels.split(":"); int need = labelNum - lables.length; if (need >= 0) { int rounds = need / 26; rounds++; // we need rounds +1 for (int i = 0; i < rounds; i++) { String[] newLables = new String[26]; for (int j = 0; j < lables.length; j++) { newLables[j] = lables[i] + lables[j]; } lables = (String[]) ArrayUtils.addAll(lables, newLables); } } return lables; } // additional constroctor for partial credit public AnswerBean(String ptext, Long pseq, String plabel, String pfdbk, Boolean pcorr, String pgrade, Double pscore, String pCredit) { this.text = ptext; this.sequence = pseq; this.label = plabel; this.feedback = pfdbk; this.isCorrect = pcorr; this.partialCredit = pCredit; } public int compareTo(Object o) { if (o == null || getSequence() == null || ((AnswerBean) o).getSequence() == null) { return -1; } else { return getSequence().compareTo(((AnswerBean) o).getSequence()); } } // for EMI questions public String getCorrectOptionLabels() { return correctOptionLabels; } // for EMI questions public void setCorrectOptionLabels(String correctOptionLabels) { if (correctOptionLabels != null) correctOptionLabels = correctOptionLabels.trim().toUpperCase(); String optionLabel = null; String temp = ""; // remove white space and delimiter characters for (int i = 0; i < correctOptionLabels.length(); i++) { optionLabel = correctOptionLabels.substring(i, i + 1); if (optionLabel.trim().equals("") || ItemDataIfc.ANSWER_OPTION_VALID_DELIMITERS.contains(optionLabel)) continue; temp += optionLabel; } this.correctOptionLabels = temp; } // for EMI questions public int correctOptionsCount() { if (correctOptionLabels == null || correctOptionLabels.trim().equals("")) return 0; return correctOptionLabels.length(); } // --mustansar for partial credit public String getPartialCredit() { return partialCredit; } public void setPartialCredit(String pCredit) { this.partialCredit = pCredit; } //Now Called from ItemAddListener because of cross-field validation public boolean isValidCorrectOptionLabels(String emiAnswerOptionLabels, FacesContext context) { boolean isValid = true; String q = ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages", "q"); if (correctOptionLabels == null || correctOptionLabels.trim().equals("")) { isValid = false; String correct_option_labels_error = ContextUtil.getLocalizedString( "org.sakaiproject.tool.assessment.bundle.AuthorMessages", "correct_option_labels_error"); FacesMessage message = new FacesMessage(correct_option_labels_error + getSequence()); context.addMessage(null, message); return isValid; } String optionLabels = correctOptionLabels.trim().toUpperCase(); String processed = ""; ItemAuthorBean itemauthorbean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor"); ItemBean itemBean = itemauthorbean.getCurrentItem(); for (int i = 0; i < optionLabels.length(); i++) { String optionLabel = optionLabels.substring(i, i + 1); if (optionLabel.equals("") || ItemDataIfc.ANSWER_OPTION_VALID_DELIMITERS.contains(optionLabel)) continue; if (!emiAnswerOptionLabels.contains(optionLabel)) { isValid = false; String please_select_from_available = ContextUtil.getLocalizedString( "org.sakaiproject.tool.assessment.bundle.AuthorMessages", "please_select_from_available"); FacesMessage message = new FacesMessage(MessageFormat.format(please_select_from_available, new Object[] { optionLabels, itemauthorbean.getItemNo() == null ? "" : itemauthorbean.getItemNo(), getSequence(), emiAnswerOptionLabels })); context.addMessage(null, message); break; } if (processed.contains(optionLabel)) { isValid = false; String duplicate_responses = ContextUtil.getLocalizedString( "org.sakaiproject.tool.assessment.bundle.AuthorMessages", "duplicate_responses"); FacesMessage message = new FacesMessage(duplicate_responses + " '" + optionLabel + "' - " + q + " " + itemauthorbean.getItemNo() + "(" + getSequence() + ")"); context.addMessage(null, message); break; } processed += optionLabel; } return isValid; } public String getRequiredOptionsCount() { return requiredOptionsCount; } public void setRequiredOptionsCount(String requiredOptionsCount) { this.requiredOptionsCount = requiredOptionsCount; } public Double getScore() { return score; } public void setScore(Double score) { this.score = score; } public Boolean getScoreUserSet() { return scoreUserSet; } public void setScoreUserSet(Boolean scoreUserSet) { this.scoreUserSet = scoreUserSet; } //for EMI - Attachments at Answer Level public List getAttachmentList() { return attachmentList; } // Attachments at Answer Level public void setAttachmentList(List attachmentList) { this.attachmentList = attachmentList; } // for EMI - Attachments at Answer Level public boolean getHasAttachment() { if (attachmentList != null && attachmentList.size() > 0) return true; else return false; } // Attachments at Answer Level public void setHasAttachment(boolean hasAttachment) { // Do nothing - required by jsf } public String getOutcome() { return outcome; } /** * set the survey scale * @param param */ public void setOutcome(String param) { this.outcome = param; } // for EMI - Attachments at Answer Level public String addAttachmentsRedirect() { ItemAuthorBean itemAuthorBean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor"); itemAuthorBean.setCurrentAnswer(this); ToolSession currentToolSession = SessionManager.getCurrentToolSession(); // 1. load resources into session for resources mgmt page // then redirect to resources mgmt page try { List filePickerList = prepareAttachmentReferenceList(this.getAttachmentList()); currentToolSession.setAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS, filePickerList); ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); context.redirect("sakai.filepicker.helper/tool"); } catch (Exception e) { log.error("fail to redirect to attachment page: " + e.getMessage()); } return getOutcome(); } // For EMI Item Attachments /* called by SamigoJsfTool.java on exit from file picker */ public void setItemTextAttachment() { AuthorBean author = (AuthorBean) ContextUtil.lookupBean("author"); boolean isEditPendingAssessmentFlow = author.getIsEditPendingAssessmentFlow(); ItemService service = null; if (isEditPendingAssessmentFlow) { service = new ItemService(); } else { service = new PublishedItemService(); } ItemDataIfc itemData = null; ItemTextIfc itemText = null; ItemAuthorBean itemauthorbean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor"); // itemId == null => new questiion if (itemauthorbean.getItemId() != null) { try { itemData = service.getItem(itemauthorbean.getItemId()); itemText = itemData.getItemTextBySequence(getSequence()); } catch (Exception e) { log.warn(e.getMessage()); } } // list returns contains modified list of attachments, i.e. new // and old attachments. This list will be // persisted to DB if user hit Save on the Item Modifying page. List list = prepareItemTextAttachment(itemText, isEditPendingAssessmentFlow); setAttachmentList(list); } // For EMI Item Attachments private List prepareAttachmentReferenceList(List attachmentList) { List list = new ArrayList(); if (attachmentList == null) { return list; } for (int i = 0; i < attachmentList.size(); i++) { ContentResource cr = null; AttachmentIfc attach = (AttachmentIfc) attachmentList.get(i); try { log.debug("*** resourceId=" + attach.getResourceId()); cr = AssessmentService.getContentHostingService().getResource(attach.getResourceId()); } catch (PermissionException e) { log.warn("ContentHostingService.getResource() throws PermissionException=" + e.getMessage()); } catch (IdUnusedException e) { log.warn("ContentHostingService.getResource() throws IdUnusedException=" + e.getMessage()); // <-- bad sign, some left over association of question and resource, // use case: user remove resource in file picker, then exit modification without // proper cancellation by clicking at the left nav instead of "cancel". // Also in this use case, any added resource would be left orphan. AssessmentService assessmentService = new AssessmentService(); assessmentService.removeItemTextAttachment(attach.getAttachmentId().toString()); } catch (TypeException e) { log.warn("ContentHostingService.getResource() throws TypeException=" + e.getMessage()); } if (cr != null) { Reference ref = EntityManager.newReference(cr.getReference()); log.debug("*** ref=" + ref); if (ref != null) list.add(ref); } } return list; } // For EMI Item Attachments private List prepareItemTextAttachment(ItemTextIfc itemText, boolean isEditPendingAssessmentFlow) { ToolSession session = SessionManager.getCurrentToolSession(); if (session.getAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS) != null) { Set attachmentSet = new HashSet(); if (itemText != null) { attachmentSet = itemText.getItemTextAttachmentSet(); } HashMap map = getResourceIdHash(attachmentSet); ArrayList newAttachmentList = new ArrayList(); AssessmentService assessmentService = new AssessmentService(); String protocol = ContextUtil.getProtocol(); List refs = (List) session.getAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS); if (refs != null && refs.size() > 0) { Reference ref; for (int i = 0; i < refs.size(); i++) { ref = (Reference) refs.get(i); String resourceId = ref.getId(); if (map.get(resourceId) == null) { // new attachment, add log.debug("**** ref.Id=" + ref.getId()); log.debug("**** ref.name=" + ref.getProperties().getProperty(ref.getProperties().getNamePropDisplayName())); ItemTextAttachmentIfc newAttach = assessmentService.createItemTextAttachment(itemText, ref.getId(), ref.getProperties().getProperty(ref.getProperties().getNamePropDisplayName()), protocol, isEditPendingAssessmentFlow); newAttachmentList.add(newAttach); } else { // attachment already exist, let's add it to new list and // check it off from map newAttachmentList.add((ItemTextAttachmentIfc) map.get(resourceId)); map.remove(resourceId); } } } session.removeAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS); session.removeAttribute(FilePickerHelper.FILE_PICKER_CANCEL); return newAttachmentList; } else if (itemText == null) { return new ArrayList(); } else { ArrayList attachmentList = new ArrayList(); Set<ItemTextAttachmentIfc> itemTextAttachmentSet = itemText.getItemTextAttachmentSet(); for (Iterator<ItemTextAttachmentIfc> it = itemTextAttachmentSet.iterator(); it.hasNext();) { attachmentList.add(it.next()); } return attachmentList; } } private HashMap getResourceIdHash(Set attachmentSet) { HashMap map = new HashMap(); if (attachmentSet != null) { Iterator iter = attachmentSet.iterator(); while (iter.hasNext()) { ItemTextAttachmentIfc attach = (ItemTextAttachmentIfc) iter.next(); map.put(attach.getResourceId(), attach); } } return map; } // for EMI - Attachments at Answer Level private HashMap resourceHash = new HashMap(); public HashMap getResourceHash() { return resourceHash; } public void setResourceHash(HashMap resourceHash) { this.resourceHash = resourceHash; } public void validatePartialCredit(FacesContext context, UIComponent toValidate, Object value) { Integer pCredit = null; boolean isValid = true; if ("0.0".equals(value.toString())) { pCredit = 0; } else { try { pCredit = Integer.parseInt(value.toString()); } catch (NumberFormatException e) { isValid = false; } } if (isValid && (pCredit == null || pCredit < 0 || pCredit > 99)) { isValid = false; } if (!isValid) { ((UIInput) toValidate).setValid(false); FacesMessage message = new FacesMessage(); message.setSeverity(FacesMessage.SEVERITY_ERROR); String summary = ContextUtil.getLocalizedString( "org.sakaiproject.tool.assessment.bundle.AuthorMessages", "partial_credit_limit_summary"); String detail = ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages", "partial_credit_limit_detail"); message.setSummary(summary); message.setDetail(detail); context.addMessage(toValidate.getClientId(context), message); } } }