@Override
  public Object visit(
      TransactionStatement transactionStatement,
      EOLPrinterContext context,
      EolVisitorController<EOLPrinterContext, Object> controller) {
    String result = "transaction";
    if (transactionStatement.getNames() != null) {
      Iterator<NameExpression> iterator = transactionStatement.getNames().iterator();
      while (iterator.hasNext()) {
        result += controller.visit(iterator.next(), context);
        if (iterator.hasNext()) {
          result += ", ";
        }
      }
    }

    result += " {" + context.newline();
    context.indent();

    if (transactionStatement.getBody() != null) {
      result += controller.visit(transactionStatement.getBody(), context);
    }
    result += context.newline();
    context.outdent();
    result += context.whitespace() + "}";

    return result;
  }
  @Override
  public Object visit(
      KeyValueExpression keyValue,
      EOLPrinterContext context,
      EolVisitorController<EOLPrinterContext, Object> controller) {
    String result = "";
    result +=
        controller.visit(keyValue.getKey(), context)
            + " = "
            + controller.visit(keyValue.getValue(), context);

    return result;
  }
  @Override
  public Object visit(
      NegativeOperatorExpression negativeOperatorExpression,
      TypeResolutionContext context,
      EolVisitorController<TypeResolutionContext, Object> controller) {
    controller.visit(negativeOperatorExpression.getExpr(), context);

    Expression expression = negativeOperatorExpression.getExpr(); // get the expression
    Type exprType = expression.getResolvedType();

    if (exprType instanceof BooleanType) { // if expression is of type boolean
      context.getLogBook().addError(expression, "Expression cannot be Boolean");
    }

    if (exprType instanceof StringType) { // if expression is of type string
      // handle string
      context.getLogBook().addError(expression, "Expression cannot be String");
    }

    if (exprType instanceof RealType) { // if expression is of type real
      negativeOperatorExpression.setResolvedType(EcoreUtil.copy(exprType));
    }
    if (exprType instanceof IntegerType) {
      negativeOperatorExpression.setResolvedType(EcoreUtil.copy(exprType));
    }

    return null;
  }
 @Override
 public Object visit(
     EolProgram eolProgram,
     PrinterContext context,
     EolVisitorController<PrinterContext, Object> controller) {
   String result = "";
   if (eolProgram.getModelDeclarations() != null
       && eolProgram.getModelDeclarations().size() != 0) {
     Iterator<ModelDeclarationStatement> iterator = eolProgram.getModelDeclarations().iterator();
     while (iterator.hasNext()) {
       result += controller.visit(iterator.next(), context);
       if (iterator.hasNext()) {
         result += context.newline();
       }
     }
     result += context.newline();
   }
   if (eolProgram.getImports() != null && eolProgram.getImports().size() != 0) {
     Iterator<Import> iterator = eolProgram.getImports().iterator();
     while (iterator.hasNext()) {
       result += controller.visit(iterator.next(), context);
       if (iterator.hasNext()) {
         result += context.newline();
       }
     }
     result += context.newline();
   }
   if (eolProgram.getBlock() != null) {
     result += controller.visit(eolProgram.getBlock(), context) + context.newline();
   }
   if (eolProgram.getOperations() != null && eolProgram.getOperations().size() != 0) {
     Iterator<OperationDefinition> iterator = eolProgram.getOperations().iterator();
     while (iterator.hasNext()) {
       result += controller.visit(iterator.next(), context);
       if (iterator.hasNext()) {
         result += context.newline();
       }
     }
   }
   return result;
 }
  @Override
  public Object visit(
      VariableDeclarationExpression variableDeclarationExpression,
      TypeResolutionContext context,
      EolVisitorController<TypeResolutionContext, Object> controller) {

    // visit contents first
    controller.visitContents(variableDeclarationExpression, context);

    // if create is not null
    if (variableDeclarationExpression.getCreate() != null) {

      // get the value of the create
      boolean newExpression = variableDeclarationExpression.getCreate().isVal();

      // if it is a new variable
      if (newExpression) {

        // get resolved type
        Type rawType = variableDeclarationExpression.getResolvedType();

        // we are interested in the model element types
        if (rawType instanceof ModelElementType) {

          // get the type
          ModelElementType modelElementType = (ModelElementType) rawType;

          // if the model element type is a EClass in the meta model
          if (modelElementType.getEcoreType() instanceof EClass) {

            // get the EClass
            EClass eClass = (EClass) modelElementType.getEcoreType();

            // check if the class is an interface or abstract
            if (eClass.isAbstract() || eClass.isInterface()) {

              context
                  .getLogBook()
                  .addError(
                      modelElementType, "Model element type is not instantiable"); // throw error
            }
          }
        }
      }
    }
    return null;
  }