/**
   * 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;
  }
Example #2
0
 /**
  * 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;
 }
Example #3
0
 /**
  * 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);
 }
Example #5
0
  /**
   * 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());
  }
Example #6
0
 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;
  }
Example #10
0
 public AttributeList(final QtiNode owner) {
   Assert.notNull(owner);
   this.owner = owner;
   this.attributes = new ArrayList<Attribute<?>>();
 }
Example #11
0
 /**
  * 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");
   }
 }