@Override public StringOrVariableRef parseDomAttributeValue(final String domAttributeValue) { return StringOrVariableRef.parseString(domAttributeValue); }
@Override public String toDomAttributeValue(final StringOrVariableRef value) { return value.toString(); }
@Override public void validateBasic(final ValidationContext context) { super.validateBasic(context); /* If variable reference, make sure it refers to the right type of variable */ if (value.isVariableRef()) { final Identifier variableReferenceIdentifier = value.getIdentifier(); final VariableDeclaration variableDeclaration = context.checkLocalVariableReference(owner, variableReferenceIdentifier); if (variableDeclaration!=null) { context.checkVariableType(owner, variableDeclaration, VariableType.TEMPLATE, VariableType.OUTCOME); context.checkSignature(owner, variableDeclaration, Signature.SINGLE_STRING); } } }
/** * Wrapper for {@link #evaluate(Expression, ProcessingContext)} that substitutes a replacement value and emits a * runtime warning if the result was NULL. */ public String evaluateNotNull(final Expression expression, final ProcessingContext context, final String messageOnNull, final String replacementOnNull) { final Value evaluated = evaluate(expression, context); String result; if (evaluated.isNull()) { context.fireRuntimeWarning(expression, messageOnNull); result = replacementOnNull; } else { result = ((StringValue) evaluated).stringValue(); } return result; } }
/** * @throws QtiParseException */ public static StringOrVariableRef parseString(final String string) { Assert.notNull(string); if (string.isEmpty()) { throw new QtiParseException("stringOrVariableRef must not be empty"); } if (string.charAt(0)=='{' && string.charAt(string.length()-1)=='}') { /* It's a variable reference */ final Identifier variableReferenceIdentifier = Identifier.parseString(string.substring(1, string.length()-1)); return new StringOrVariableRef(variableReferenceIdentifier); } else { /* It's a string */ return new StringOrVariableRef(string); } }
/** * Evaluates this holder. If this holds an explicit integer then its value is returned as-is. * Otherwise, the given {@link ProcessingContext} is used to look up the value of the variable * that this type refers to. The result will either be an {@link StringValue} or {@link NullValue}. * <p> * If the variable cannot be successfully resolved or is of the wrong type then a runtime error * is recorded and a {@link NullValue} will be returned. */ public Value evaluate(final Expression expression, final ProcessingContext context) { if (isConstantString()) { return constantStringValue; } else { final Value result = context.evaluateVariableValue(variableReferenceValue); if (result.hasSignature(Signature.SINGLE_STRING)) { return result; } else { context.fireRuntimeError(expression, "Variable referenced by " + variableReferenceValue + " was expected to be a single string - returning NULL"); return NullValue.INSTANCE; } } }
@Override protected Value evaluateValidSelf(final ProcessingContext context, final Value[] childValues, final int depth) { if (isAnyChildNull(childValues)) { return NullValue.INSTANCE; } final Value computedPattern = getPattern().evaluate(this, context); if (computedPattern.isNull()) { context.fireRuntimeWarning(this, "Computed value of pattern was NULL. Returning NULL"); return NullValue.INSTANCE; } final String pattern = ((StringValue) computedPattern).stringValue(); final String childString = ((StringValue) childValues[0]).toQtiString(); final boolean result = childString.matches(pattern); return BooleanValue.valueOf(result); } }