qtiscoringengine.ISECustomExpression.java Source code

Java tutorial

Introduction

Here is the source code for qtiscoringengine.ISECustomExpression.java

Source

/*******************************************************************************
 * Educational Online Test Delivery System 
 * Copyright (c) 2014 American Institutes for Research
 *     
 * Distributed under the AIR Open Source License, Version 1.0 
 * See accompanying file AIR-License-1_0.txt or at
 * 
 * http://www.smarterapp.org/documents/American_Institutes_for_Research_Open_Source_Software_License.pdf
 ******************************************************************************/
package qtiscoringengine;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import tds.itemscoringengine.IItemScorer;
import tds.itemscoringengine.ItemScore;
import tds.itemscoringengine.Proposition;
import tds.itemscoringengine.PropositionState;
import tds.itemscoringengine.ResponseInfo;
import tds.itemscoringengine.RubricContentType;
import tds.itemscoringengine.ScoringStatus;
import tds.itemscoringengine.VarBinding;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Attribute;
import org.jdom2.Element;

import qtiscoringengine.cs2java.StringHelper;
import AIR.Common.Utilities.JavaPrimitiveUtils;
import AIR.Common.Utilities.TDSStringUtils;
import AIR.Common.xml.XmlElement;
import AIR.Common.xml.XmlNamespaceManager;

public class ISECustomExpression extends Expression {
    private IItemScorer _itemScorer = null;
    private String _itemFormat = null;
    private String _rubric = null;
    private String _responseIdentifier = null;

    // A tuple used to store source/target pairs - used for bindInput and
    // bindOuput declaration parsing.
    private class NameMapping {
        public String sourceId;
        public String targetId;

        public NameMapping(String src, String tgt) {
            sourceId = src;
            targetId = tgt;
        }
    }

    private List<NameMapping> _incomingIdentifiers = new ArrayList<NameMapping>();
    private List<NameMapping> _outgoingIdentifiers = new ArrayList<NameMapping>();

    public ISECustomExpression(Element node, IItemScorer externalScorer) {
        super(node, 0, Integer.MAX_VALUE, BaseType.Boolean, Cardinality.Single);
        XmlNamespaceManager nsMgr = new XmlNamespaceManager();
        nsMgr.addNamespace("air", "http://www.air.org");

        XmlElement nodeElement = new XmlElement(node);

        _itemScorer = externalScorer;
        _itemFormat = getOperatorType(node);
        _rubric = new XmlElement(nodeElement.selectSingleNode("air:rubric", nsMgr)).getInnerXml();
        _responseIdentifier = nodeElement.selectSingleNode("air:responseComponent", nsMgr)
                .getAttributeValue("identifier");

        List<Element> bindInputsList = nodeElement.selectNodes("air:bindInput", nsMgr);
        if (bindInputsList != null) // These are the bindings going from QTI
                                    // executive to the ISE - values evaluated by
                                    // QTI and passed into ISE
        {
            for (Element incomingBinding : bindInputsList) {
                _incomingIdentifiers.add(new NameMapping(incomingBinding.getAttributeValue("sourceIdentifier"),
                        incomingBinding.getAttributeValue("targetIdentifier")));
            }
        }

        List<Element> bindOutput = nodeElement.selectNodes("air:bindOutput", nsMgr);
        if (bindOutput != null) // These are the bindings going from ISE to the QTI
                                // executive - values evaluated by ISE and made
                                // available to QTI
        {
            for (Element outgoingBinding : bindOutput) {
                _outgoingIdentifiers.add(new NameMapping(outgoingBinding.getAttributeValue("sourceIdentifier"),
                        outgoingBinding.getAttributeValue("targetIdentifier")));
                ;
            }
        }
    }

    @Override
    protected DataElement exprEvaluate(VariableBindings vb, QTIRubric rubric, List<DataElement> paramValues) {
        String response = vb.getVariable(_responseIdentifier).toString();

        ResponseInfo rinfo = new ResponseInfo(_itemFormat, "", response, _rubric, RubricContentType.ContentString,
                null, false) {
            {
                setOutgoingBindings(Arrays.asList(VarBinding.ALL)); // We alwyas ask
                                                                    // for ALL from
                                                                    // expressions and
                                                                    // leave it to the
                                                                    // QTI executive
                                                                    // to decide which
                                                                    // ones to expose
                                                                    // to the caller
                                                                    // IncomingBindings = GetIncomingBindings(_incomingIdentifiers) // These
                                                                    // are bindings we can pass from QTI to ISE .. **TODO**
            }
        };

        ItemScore score = _itemScorer.ScoreItem(rinfo, null);

        rubric.getResponseProcessingState().add(score);

        if (score.getScoreInfo().getRationale().getBindings() != null) {
            for (final VarBinding binding : score.getScoreInfo().getRationale().getBindings()) {
                // Look through the bindOutput declarations to see whether this binding
                // from ISE needs to be bound to a QTI variable and to which one
                NameMapping bindOutputDirective = (NameMapping) CollectionUtils.find(_outgoingIdentifiers,
                        new Predicate() {

                            @Override
                            public boolean evaluate(Object object) {
                                NameMapping x = (NameMapping) object;
                                return StringUtils.equals(x.sourceId, binding.getName());
                            }
                        });

                if (bindOutputDirective.targetId != null && vb.getVariable(bindOutputDirective.targetId) != null) // this
                                                                                                                  // is
                                                                                                                  // added
                                                                                                                  // so
                                                                                                                  // that
                                                                                                                  // only
                                                                                                                  // variables
                                                                                                                  // declared
                                                                                                                  // in
                                                                                                                  // the
                                                                                                                  // QTI
                                                                                                                  // rubric
                                                                                                                  // will
                                                                                                                  // be
                                                                                                                  // bound
                                                                                                                  // and
                                                                                                                  // we
                                                                                                                  // can
                                                                                                                  // exclude
                                                                                                                  // all
                                                                                                                  // the
                                                                                                                  // internal
                                                                                                                  // native
                                                                                                                  // scoring
                                                                                                                  // engine
                                                                                                                  // bindings
                {
                    vb.setVariable(bindOutputDirective.targetId, DataElement.create(binding.getValue(),
                            rubric.getOutcomeVariableBaseType(bindOutputDirective.targetId)));
                }
            }
        }
        if (score.getScoreInfo().getRationale().getPropositions() != null) {
            for (final Proposition proposition : score.getScoreInfo().getRationale().getPropositions()) {
                // Look through the bindOutput declarations to see whether this binding
                // from ISE needs to be bound to a QTI variable and to which one
                NameMapping bindOutputDirective = (NameMapping) CollectionUtils.find(_outgoingIdentifiers,
                        new Predicate() {
                            @Override
                            public boolean evaluate(Object object) {
                                NameMapping x = (NameMapping) object;
                                return StringUtils.equals(x.sourceId, proposition.getName());
                            }
                        });

                if (bindOutputDirective.targetId != null && vb.getVariable(bindOutputDirective.targetId) != null) // this
                                                                                                                  // is
                                                                                                                  // added
                                                                                                                  // so
                                                                                                                  // that
                                                                                                                  // only
                                                                                                                  // variables
                                                                                                                  // declared
                                                                                                                  // in
                                                                                                                  // the
                                                                                                                  // QTI
                                                                                                                  // rubric
                                                                                                                  // will
                                                                                                                  // be
                                                                                                                  // bound
                                                                                                                  // and
                                                                                                                  // we
                                                                                                                  // can
                                                                                                                  // exclude
                                                                                                                  // all
                                                                                                                  // the
                                                                                                                  // internal
                                                                                                                  // native
                                                                                                                  // scoring
                                                                                                                  // engine
                                                                                                                  // propositions
                {
                    vb.setVariable(bindOutputDirective.targetId,
                            DataElement.create(
                                    TDSStringUtils.getCSharpBooleanToString(
                                            proposition.getState() == PropositionState.Asserted),
                                    BaseType.Boolean));
                }
            }
        }

        return score.getScoreInfo().getStatus() == ScoringStatus.Scored
                ? DataElement.create("true", BaseType.Boolean)
                : DataElement.create("false", BaseType.Boolean);
    }

    private static String getOperatorType(Element customOperatorNode) {
        for (Attribute attribute : customOperatorNode.getAttributes()) {
            if (StringUtils.equalsIgnoreCase(attribute.getName(), "CLASS")) {
                return attribute.getValue();
            }
        }
        return "";
    }
}