package org.nlamah.QL.TypeChecker;
import java.util.ArrayList;
import java.util.List;
import org.nlamah.QL.Model.Expression.Literal.IdentifierLiteral;
import org.nlamah.QL.Model.Form.Form;
import org.nlamah.QL.Model.Form.Abstract.FormQuestion;
import org.nlamah.QL.Error.QLDoubleDeclarationError;
import org.nlamah.QL.Error.DoubleQuestionLabelWarning;
import org.nlamah.QL.Error.TooLateDeclaredQuestionError;
import org.nlamah.QL.Error.UndeclaredFormQuestionError;
import org.nlamah.QBase.Error.QBaseError;
import org.nlamah.QBase.Error.QBaseException;
import org.nlamah.QBase.Tools.QLTools;
import org.nlamah.QBase.TypeChecker.QBaseAbstractTypeChecker;
public class QLTypeChecker extends QBaseAbstractTypeChecker
{
public void check(Form form) throws QBaseException
{
checkIfQuestionsAreDeclaredOnlyOnce(form);
checkIfReferenceQuestionsAreDeclaredAtAll(form);
checkIfReferencedQuestionsAreDeclaredBeforeReferral(form);
questionsAreDeclaredInRightScopeWithNoCyclicDependency(form);
interconnectReferencesWithDeclarations(form);
checkForTypeMismatchErrors(form);
checkForDuplicateQuestionLabels(form);
}
private void checkIfQuestionsAreDeclaredOnlyOnce(Form form) throws QBaseException
{
List<FormQuestion> list = FormQuestion.getListWithDuplicatedQuestionIdentifiers(form.questions());
if (list.size() > 0)
{
for (FormQuestion duplicateQuestion : list)
{
errors.add(new QLDoubleDeclarationError(duplicateQuestion.identifier(), QLTools.getQuestionsWithIdentifier(form.questions(), duplicateQuestion.identifier())));
}
}
checkForErrors();
}
private void checkIfReferenceQuestionsAreDeclaredAtAll(Form form) throws QBaseException
{
for (IdentifierLiteral identifier : form.referencedQuestions())
{
if (QLTools.getQuestionsWithIdentifier(form.questions(), identifier).size() == 0)
{
errors.add(new UndeclaredFormQuestionError(identifier));
}
}
checkForErrors();
}
private void checkIfReferencedQuestionsAreDeclaredBeforeReferral(Form form) throws QBaseException
{
for (IdentifierLiteral identifier : form.referencedQuestions())
{
questionIsDeclaredBeforeReferredTo(identifier, form);
}
checkForErrors();
}
private void questionIsDeclaredBeforeReferredTo(IdentifierLiteral identifier, Form form) throws QBaseException
{
FormQuestion foundDeclaration = QLTools.getQuestionWithIdentifier(form.questions(), identifier);
if (identifier.startsOnLine < foundDeclaration.startsOnLine)
{
errors.add(new TooLateDeclaredQuestionError(identifier, foundDeclaration));
}
else if (identifier.startsOnLine == foundDeclaration.startsOnLine)
{
if (identifier.startsAtCharacterPosition < foundDeclaration.startsAtCharacterPosition)
{
errors.add(new TooLateDeclaredQuestionError(identifier, foundDeclaration));
}
}
checkForErrors();
}
private void questionsAreDeclaredInRightScopeWithNoCyclicDependency(Form form) throws QBaseException
{
for (IdentifierLiteral identifier : form.referencedQuestions())
{
OutOfScopeDeclarationChecker outOfScopeChecker = new OutOfScopeDeclarationChecker(identifier);
errors.addAll(outOfScopeChecker.errors());
}
checkForErrors();
}
private void interconnectReferencesWithDeclarations(Form form)
{
for (IdentifierLiteral identifier : form.referencedQuestions())
{
identifier.setCorrespondingQuestion(QLTools.getQuestionWithIdentifier(form.questions(), identifier));
}
}
private void checkForTypeMismatchErrors(Form form) throws QBaseException
{
List<QBaseError> identifierErrors = new ArrayList<QBaseError>();
for (IdentifierLiteral identifier : form.referencedQuestions())
{
IdentifierTypeChecker identifierChecker = new IdentifierTypeChecker(identifier);
identifierErrors.addAll(identifierChecker.errors());
}
errors.addAll(identifierErrors);
if (identifierErrors.size() == 0)
{
ExpressionTypeChecker expressionChecker = new ExpressionTypeChecker(form);
errors.addAll(expressionChecker.errors());
}
checkForErrors();
}
private void checkForDuplicateQuestionLabels(Form form)
{
List<FormQuestion> list = FormQuestion.getListWithDuplicatedQuestionTexts(form.questions());
if (list.size() > 0)
{
for (FormQuestion question : list)
{
warnings.add(new DoubleQuestionLabelWarning(QLTools.getQuestionsWithQuestionText(form.questions(), question.questionText())));
}
}
}
}