/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.ims.qti21.manager; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.stream.Collectors; import javax.persistence.TypedQuery; import org.olat.basesecurity.GroupRoles; import org.olat.core.commons.persistence.DB; import org.olat.core.util.StringHelper; import org.olat.ims.qti21.AssessmentItemSession; import org.olat.ims.qti21.AssessmentResponse; import org.olat.ims.qti21.AssessmentTestSession; import org.olat.ims.qti21.model.QTI21StatisticSearchParams; import org.olat.ims.qti21.model.ResponseLegality; import org.olat.ims.qti21.model.jpa.AssessmentResponseImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import uk.ac.ed.ph.jqtiplus.types.ResponseData.ResponseDataType; /** * * Initial date: 29.01.2016<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ @Service public class AssessmentResponseDAO { @Autowired private DB dbInstance; public AssessmentResponse createAssessmentResponse(AssessmentTestSession assessmentTestSession, AssessmentItemSession assessmentItemSession, String responseIdentifier, ResponseLegality legality, ResponseDataType type) { AssessmentResponseImpl response = new AssessmentResponseImpl(); Date now = new Date(); response.setCreationDate(now); response.setLastModified(now); response.setResponseDataType(type.name()); response.setResponseLegality(legality.name()); response.setAssessmentItemSession(assessmentItemSession); response.setAssessmentTestSession(assessmentTestSession); response.setResponseIdentifier(responseIdentifier); return response; } public List<AssessmentResponse> getResponses(AssessmentItemSession assessmentItemSession) { StringBuilder sb = new StringBuilder(); sb.append("select response from qtiassessmentresponse response where") .append(" response.assessmentItemSession.key=:assessmentItemSessionKey"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), AssessmentResponse.class) .setParameter("assessmentItemSessionKey", assessmentItemSession.getKey()) .getResultList(); } public void save(Collection<AssessmentResponse> responses) { if(responses != null && responses.isEmpty()) return; for(AssessmentResponse response:responses) { if(response.getKey() != null) { dbInstance.getCurrentEntityManager().merge(response); } else { dbInstance.getCurrentEntityManager().persist(response); } } } /** * Check if there are some responses from a terminated session. * * @param courseEntry * @param subIdent * @param testEntry * @return */ public boolean hasResponses(QTI21StatisticSearchParams searchParams) { StringBuilder sb = new StringBuilder(); sb.append("select response.key from qtiassessmentresponse response ") .append(" inner join response.assessmentItemSession itemSession") .append(" inner join itemSession.assessmentTestSession testSession") .append(" where testSession.repositoryEntry.key=:repoEntryKey") .append(" and testSession.testEntry.key=:testEntryKey") .append(" and testSession.subIdent=:subIdent") .append(" and testSession.finishTime is not null and testSession.authorMode=false") .append(" and ("); if(searchParams.isViewAllUsers()) { sb.append(" testSession.identity.key is not null"); } else if(searchParams.getLimitToGroups() != null) { sb.append(" testSession.identity.key in (select membership.identity.key from bgroupmember as membership, repoentrytogroup as rel") .append(" where rel.entry.key=:repoEntryKey and rel.group.key=membership.group.key and rel.group.key in (:limitGroupKeys)") .append(" and membership.role='").append(GroupRoles.participant.name()).append("'") .append(" )"); } else if(searchParams.getLimitToIdentities() != null) { sb.append(" testSession.identity.key in (select membership.identity.key from bgroupmember as membership, repoentrytogroup as rel") .append(" where rel.entry.key=:repoEntryKey and rel.group.key=membership.group.key and membership.identity.key in (:limitIdentityKeys)") .append(" and membership.role='").append(GroupRoles.participant.name()).append("'") .append(" )"); } else { sb.append(" testSession.identity.key in (select membership.identity.key from bgroupmember as membership, repoentrytogroup as rel") .append(" where rel.entry.key=:repoEntryKey and rel.group.key=membership.group.key ") .append(" and membership.role='").append(GroupRoles.participant.name()).append("'") .append(" )"); } if(searchParams.isViewAnonymUsers()) { sb.append(" or testSession.anonymousIdentifier is not null"); } sb.append(")"); List<Long> responses = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Long.class) .setParameter("repoEntryKey", searchParams.getCourseEntry().getKey()) .setParameter("testEntryKey", searchParams.getTestEntry().getKey()) .setParameter("subIdent", searchParams.getNodeIdent()) .setFirstResult(0) .setMaxResults(1) .getResultList(); return responses.size() > 0 && responses.get(0) != null; } public List<AssessmentResponse> getResponse(QTI21StatisticSearchParams searchParams) { StringBuilder sb = new StringBuilder(); sb.append("select response from qtiassessmentresponse response ") .append(" inner join fetch response.assessmentItemSession itemSession") .append(" inner join fetch itemSession.assessmentTestSession testSession") .append(" inner join fetch testSession.assessmentEntry assessmentEntry") .append(" left join assessmentEntry.identity as ident") .append(" left join ident.user as usr") .append(" where testSession.testEntry.key=:testEntryKey") .append(" and testSession.finishTime is not null and testSession.authorMode=false"); if(searchParams.getCourseEntry() != null || searchParams.getTestEntry() != null) { sb.append(" and testSession.repositoryEntry.key=:repoEntryKey"); } if(StringHelper.containsNonWhitespace(searchParams.getNodeIdent())) { sb.append(" and testSession.subIdent=:subIdent"); } sb.append(" and ("); if(searchParams.getLimitToGroups() != null) { sb.append(" testSession.identity.key in (select membership.identity.key from bgroupmember as membership, repoentrytogroup as rel") .append(" where rel.entry.key=:repoEntryKey and rel.group.key=membership.group.key and rel.group.key in (:limitGroupKeys)"); if(!searchParams.isViewAllUsers()) { sb.append(" and membership.role='").append(GroupRoles.participant.name()).append("'"); } sb.append(" )"); } else if(searchParams.getLimitToIdentities() != null) { sb.append(" testSession.identity.key in (select membership.identity.key from bgroupmember as membership, repoentrytogroup as rel") .append(" where rel.entry.key=:repoEntryKey and rel.group.key=membership.group.key and membership.identity.key in (:limitIdentityKeys)") .append(" and membership.role='").append(GroupRoles.participant.name()).append("'") .append(" )"); } else if(searchParams.isViewAllUsers()) { sb.append(" testSession.identity.key is not null"); } else { sb.append(" testSession.identity.key in (select membership.identity.key from bgroupmember as membership, repoentrytogroup as rel") .append(" where rel.entry.key=:repoEntryKey and rel.group.key=membership.group.key ") .append(" and membership.role='").append(GroupRoles.participant.name()).append("'") .append(" )"); } if(searchParams.isViewAnonymUsers()) { sb.append(" or testSession.anonymousIdentifier is not null"); } sb.append(")"); //need to be anonymized sb.append(" order by usr.lastName, testSession.key, itemSession.key"); TypedQuery<AssessmentResponse> query = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), AssessmentResponse.class) .setParameter("testEntryKey", searchParams.getTestEntry().getKey()); if(searchParams.getCourseEntry() != null) { query.setParameter("repoEntryKey", searchParams.getCourseEntry().getKey()); } else { query.setParameter("repoEntryKey", searchParams.getTestEntry().getKey()); } if(StringHelper.containsNonWhitespace(searchParams.getNodeIdent())) { query.setParameter("subIdent", searchParams.getNodeIdent()); } if(searchParams.getLimitToGroups() != null && searchParams.getLimitToGroups().size() > 0) { List<Long> keys = searchParams.getLimitToGroups().stream() .map(group -> group.getKey()).collect(Collectors.toList()); query.setParameter("limitGroupKeys", keys); } if(searchParams.getLimitToIdentities() != null && searchParams.getLimitToIdentities().size() > 0) { List<Long> keys = searchParams.getLimitToIdentities().stream() .map(group -> group.getKey()).collect(Collectors.toList()); query.setParameter("limitIdentityKeys", keys); } return query.getResultList(); } }