/** * Starts new {@link CandidateSession} for the given {@link User} on the given {@link Delivery} * * <p>NB: No checks are made on whether the {@link User} should be allowed to start a session on * this {@link Delivery}. */ public CandidateSession launchCandidateSession( final User candidate, final Delivery delivery, final boolean authorMode, final String lisOutcomeServiceUrl, final String lisResultSourcedid) throws CandidateException { Assert.notNull(candidate, "candidate"); Assert.notNull(delivery, "delivery"); /* Make sure Candidate's account is not disabled */ if (candidate.isLoginDisabled()) { logAndThrowLaunchException( candidate, delivery, CandidateExceptionReason.USER_ACCOUNT_DISABLED); } /* Make sure Delivery is runnable */ if (delivery.getAssessment() == null) { logAndThrowLaunchException( candidate, delivery, CandidateExceptionReason.LAUNCH_INCOMPLETE_DELIVERY); } /* If the candidate already has any non-terminated sessions open for this Delivery, * then we shall reconnect to the (most recent) session instead of creating a new one. */ final List<CandidateSession> existingSessions = candidateSessionDao.getNonTerminatedForDeliveryAndCandidate(delivery, candidate); if (!existingSessions.isEmpty()) { final CandidateSession mostRecent = existingSessions.get(existingSessions.size() - 1); auditLogger.recordEvent( "Reconnected to existing CandidateSession #" + mostRecent.getId() + " on Delivery #" + delivery.getId()); return mostRecent; } /* No existing session to reconnect to, so create a new session. * * (NB: The session will later need to be explicitly entered before anything can be done * with it.) */ final CandidateSession candidateSession = new CandidateSession(); candidateSession.setLisOutcomeServiceUrl(lisOutcomeServiceUrl); candidateSession.setLisResultSourcedid(lisResultSourcedid); candidateSession.setCandidate(candidate); candidateSession.setDelivery(delivery); candidateSession.setAuthorMode(authorMode); candidateSession.setFinishTime(null); candidateSession.setTerminationTime(null); candidateSession.setExploded(false); candidateSessionDao.persist(candidateSession); auditLogger.recordEvent( "Created and initialised new CandidateSession #" + candidateSession.getId() + " on Delivery #" + delivery.getId()); return candidateSession; }
/** * Gets (first) templateDeclaration with given identifier, or null if no such variable is defined. * * @param identifier given identifier * @return templateDeclaration with given identifier or null */ public TemplateDeclaration getTemplateDeclaration(final Identifier identifier) { Assert.notNull(identifier); for (final TemplateDeclaration declaration : getTemplateDeclarations()) { if (identifier.equals(declaration.getIdentifier())) { return declaration; } } return null; }
/** * Gets (first) explicitly-defined outcomeDeclaration with given identifier, or null if no such * declaration exists. * * <p>NB: Doesn't include the implicitly-defined {@link * QtiConstants#VARIABLE_COMPLETION_STATUS_NAME} variable * * @param identifier given identifier * @return outcomeDeclaration with given identifier or null * @see #getCompletionStatusOutcomeDeclaration() */ @Override public OutcomeDeclaration getOutcomeDeclaration(final Identifier identifier) { Assert.notNull(identifier); for (final OutcomeDeclaration declaration : getOutcomeDeclarations()) { if (identifier.equals(declaration.getIdentifier())) { return declaration; } } return null; }
/** * Starts new {@link CandidateSession} for the current thread's {@link User} on the given {@link * Delivery} * * <p>NB: No checks are made on whether the {@link User} should be allowed to start a session on * this {@link Delivery}. */ public CandidateSession launchCandidateSession( final Delivery delivery, final boolean authorMode, final String lisOutcomeServiceUrl, final String lisResultSourcedid) throws CandidateException { Assert.notNull(delivery, "delivery"); final User candidate = identityService.assertCurrentThreadUser(); return launchCandidateSession( candidate, delivery, authorMode, lisOutcomeServiceUrl, lisResultSourcedid); }
/** * Gets attribute with given local name and namespace URI or null (if attribute is not found). * Silent parameter is useful for support of unknown attributes. * * @param localName name of requested attribute * @param silent if exception should be thrown in case attribute is not found * @return attribute with given name * @throws QtiAttributeException if silent is false and if attribute is not found */ private Attribute<?> get( final String localName, final String namespaceUri, final boolean silent) { Assert.notNull(localName, "localName"); Assert.notNull(namespaceUri, "namespaceUri"); for (final Attribute<?> attribute : attributes) { if (attribute.getLocalName().equals(localName) && attribute.getNamespaceUri().equals(namespaceUri)) { return attribute; } } if (silent) { return null; } throw new QtiAttributeException( "Cannot find attribute with namespace '" + namespaceUri + "' and local name '" + localName + "' in Node with XPath " + owner.computeXPath()); }
private static final <V> void loadAttribute( final Attribute<V> attribute, final Element element, final String stringValue, final LoadingContext context) { Assert.notNull(stringValue, "stringValue"); V value = null; try { value = attribute.parseDomAttributeValue(stringValue); } catch (final QtiParseException ex) { context.modelBuildingError(ex, element); } attribute.setValue(value); }
public CandidateEvent recordCandidateTestEvent( final CandidateSession candidateSession, final CandidateTestEventType testEventType, final CandidateItemEventType itemEventType, final TestPlanNodeKey itemKey, final TestSessionState testSessionState, final NotificationRecorder notificationRecorder) { Assert.notNull(candidateSession, "candidateSession"); Assert.notNull(testEventType, "testEventType"); Assert.notNull(testSessionState, "testSessionState"); /* Create event */ final CandidateEvent event = new CandidateEvent(); event.setCandidateSession(candidateSession); event.setTestEventType(testEventType); event.setItemEventType(itemEventType); if (itemKey != null) { event.setTestItemKey(itemKey.toString()); } event.setTimestamp(requestTimestampContext.getCurrentRequestTimestamp()); /* Store event */ candidateEventDao.persist(event); /* Store test session state */ storeTestSessionState(event, testSessionState); /* Now store processing notifications */ if (notificationRecorder != null) { for (final Notification notification : notificationRecorder.getNotifications()) { recordNotification(event, notification); } } return event; }
/** * Wraps the given {@link ItemSessionState} in a {@link ItemSessionController}. * * <p>It is assumed that the item was runnable, so this will never return null. */ public ItemSessionController createItemSessionController( final CandidateSession candidateSession, final ItemSessionState itemSessionState, final NotificationRecorder notificationRecorder) { final User candidate = candidateSession.getCandidate(); final Delivery delivery = candidateSession.getDelivery(); ensureItemDelivery(delivery); Assert.notNull(itemSessionState, "itemSessionState"); /* Try to resolve the underlying JQTI+ object */ final AssessmentPackage assessmentPackage = assessmentDataService.ensureSelectedAssessmentPackage(delivery); final ItemProcessingMap itemProcessingMap = assessmentObjectManagementService.getItemProcessingMap(assessmentPackage); if (itemProcessingMap == null) { throw new QtiWorksLogicException("Expected this item to be runnable"); } /* Create config for ItemSessionController */ final ItemDeliverySettings itemDeliverySettings = (ItemDeliverySettings) assessmentDataService.getEffectiveDeliverySettings(candidate, delivery); final ItemSessionControllerSettings itemSessionControllerSettings = new ItemSessionControllerSettings(); itemSessionControllerSettings.setTemplateProcessingLimit( computeTemplateProcessingLimit(itemDeliverySettings)); itemSessionControllerSettings.setMaxAttempts(itemDeliverySettings.getMaxAttempts()); /* Create controller and wire up notification recorder (if passed) */ final ItemSessionController result = new ItemSessionController( jqtiExtensionManager, itemSessionControllerSettings, itemProcessingMap, itemSessionState); if (notificationRecorder != null) { result.addNotificationListener(notificationRecorder); } return result; }
/** * Wraps the given {@link TestSessionState} in a {@link TestSessionController}. * * <p>It is assumed that the test was runnable, so this will never return null. */ public TestSessionController createTestSessionController( final CandidateSession candidateSession, final TestSessionState testSessionState, final NotificationRecorder notificationRecorder) { final User candidate = candidateSession.getCandidate(); final Delivery delivery = candidateSession.getDelivery(); ensureTestDelivery(delivery); Assert.notNull(testSessionState, "testSessionState"); /* Try to resolve the underlying JQTI+ object */ final AssessmentPackage assessmentPackage = assessmentDataService.ensureSelectedAssessmentPackage(delivery); final TestProcessingMap testProcessingMap = assessmentObjectManagementService.getTestProcessingMap(assessmentPackage); if (testProcessingMap == null) { return null; } /* Create config for TestSessionController */ final TestDeliverySettings testDeliverySettings = (TestDeliverySettings) assessmentDataService.getEffectiveDeliverySettings(candidate, delivery); final TestSessionControllerSettings testSessionControllerSettings = new TestSessionControllerSettings(); testSessionControllerSettings.setTemplateProcessingLimit( computeTemplateProcessingLimit(testDeliverySettings)); /* Create controller and wire up notification recorder (if passed) */ final TestSessionController result = new TestSessionController( jqtiExtensionManager, testSessionControllerSettings, testProcessingMap, testSessionState); if (notificationRecorder != null) { result.addNotificationListener(notificationRecorder); } return result; }
public AttributeList(final QtiNode owner) { Assert.notNull(owner); this.owner = owner; this.attributes = new ArrayList<Attribute<?>>(); }
/** * Constructs <code>StringValue</code> from given <code>String</code> representation. * * @param value <code>String</code> representation of <code>StringValue</code> */ public StringValue(final String value) { Assert.notNull(value); this.stringValue = value; }
/** Evaluates this Expression (and its children) */ @Override public final Value evaluate(final ProcessingContext context) { final Value result = evaluate(context, 0); Assert.notNull(result, "result of evaluation"); return result; }
private void ensureTestDelivery(final Delivery delivery) { Assert.notNull(delivery, "delivery"); if (delivery.getAssessment().getAssessmentType() != AssessmentObjectType.ASSESSMENT_TEST) { throw new IllegalArgumentException("Expected " + delivery + " to correspond to a Test"); } }
public void ensureItemDelivery(final Delivery delivery) { Assert.notNull(delivery, "delivery"); if (delivery.getAssessment().getAssessmentType() != AssessmentObjectType.ASSESSMENT_ITEM) { throw new IllegalArgumentException("Expected " + delivery + " to correspond to an Item"); } }