private <SE> Stack<ITranslator<?, ?, ?, ?, ?, ?>> prepareExpressionStack(
     final SE expression, final Class<SE> clazz) {
   final Stack<ITranslator<?, ?, ?, ?, ?, ?>> current = new Stack<ITranslator<?, ?, ?, ?, ?, ?>>();
   boolean canTranslate = false;
   for (final ITranslator<?, ?, ?, ?, ?, ?> trans : mTranslationSequence) {
     current.push(trans);
     if (trans.getSourceExpressionClass().isAssignableFrom(clazz)) {
       canTranslate = true;
     }
   }
   if (!canTranslate) {
     throw new IllegalArgumentException(
         "You cannot translate "
             + expression.getClass().getName()
             + " with this backtranslation service, as there is no compatible "
             + "ITranslator available. Available translators: "
             + toString());
   }
   if (!current.peek().getSourceExpressionClass().isAssignableFrom(clazz)) {
     throw new IllegalArgumentException(
         "You cannot translate "
             + expression.getClass().getName()
             + " with this backtranslation service, as the last ITranslator in "
             + "this chain is not compatible. Available translators: "
             + toString());
   }
   return current;
 }
 private boolean isAllowedNext(
     final ITranslator<?, ?, ?, ?, ?, ?> current, final ITranslator<?, ?, ?, ?, ?, ?> next) {
   // source is e.g. RcfgElement, target is e.g. BoogieASTNode
   // meaning, source is the output of the tool, target the input
   return current.getSourceExpressionClass() == next.getTargetExpressionClass()
       && current.getSourceTraceElementClass() == next.getTargetTraceElementClass();
 }
  @Override
  public <STE, SE> IBacktranslatedCFG<?, ?> translateCFG(final IBacktranslatedCFG<?, STE> cfg) {
    final Stack<ITranslator<?, ?, ?, ?, ?, ?>> current = new Stack<ITranslator<?, ?, ?, ?, ?, ?>>();
    boolean canTranslate = false;
    for (final ITranslator<?, ?, ?, ?, ?, ?> trans : mTranslationSequence) {
      current.push(trans);
      if (trans.getSourceTraceElementClass().isAssignableFrom(cfg.getTraceElementClass())) {
        canTranslate = true;
      }
    }
    if (!canTranslate) {
      throw new IllegalArgumentException(
          "You cannot translate "
              + cfg
              + " with this backtranslation service, as there is no compatible ITranslator available");
    }

    if (!current.peek().getSourceTraceElementClass().isAssignableFrom(cfg.getTraceElementClass())) {
      throw new IllegalArgumentException(
          "You cannot translate "
              + cfg
              + " with this backtranslation service, as the last ITranslator in this chain is not compatible");
    }
    return translateCFG(current, cfg);
  }
 @SuppressWarnings("unchecked")
 private <TE, SE> TE translateExpression(
     final Stack<ITranslator<?, ?, ?, ?, ?, ?>> remaining, final SE expression) {
   if (remaining.isEmpty()) {
     return (TE) expression;
   } else {
     final ITranslator<?, ?, SE, TE, ?, ?> tmp = (ITranslator<?, ?, SE, TE, ?, ?>) remaining.pop();
     return translateExpression(remaining, tmp.translateExpression(expression));
   }
 }
 @SuppressWarnings("unchecked")
 private <TTE, STE> List<TTE> translateTrace(
     final Stack<ITranslator<?, ?, ?, ?, ?, ?>> remaining, final List<STE> trace) {
   if (remaining.isEmpty()) {
     return (List<TTE>) trace;
   } else {
     final ITranslator<STE, TTE, ?, ?, ?, ?> translator =
         (ITranslator<STE, TTE, ?, ?, ?, ?>) remaining.pop();
     return translateTrace(remaining, translator.translateTrace(trace));
   }
 }
 @SuppressWarnings("unchecked")
 private <STE, TTE, SE, TE, SVL, TVL> IBacktranslatedCFG<TVL, TTE> translateCFG(
     final Stack<ITranslator<?, ?, ?, ?, ?, ?>> remaining,
     final IBacktranslatedCFG<SVL, STE> cfg) {
   if (remaining.isEmpty()) {
     return (IBacktranslatedCFG<TVL, TTE>) cfg;
   } else {
     final ITranslator<STE, TTE, SE, TE, SVL, TVL> translator =
         (ITranslator<STE, TTE, SE, TE, SVL, TVL>) remaining.pop();
     final IBacktranslatedCFG<?, TTE> translated = translator.translateCFG(cfg);
     return translateCFG(remaining, translated);
   }
 }
 @SuppressWarnings("unchecked")
 private <STE, TTE, SE, TE> IProgramExecution<TTE, TE> translateProgramExecution(
     final Stack<ITranslator<?, ?, ?, ?, ?, ?>> remaining,
     final IProgramExecution<STE, SE> programExecution) {
   if (remaining.isEmpty()) {
     return (IProgramExecution<TTE, TE>) programExecution;
   } else {
     final ITranslator<STE, TTE, SE, TE, ?, ?> translator =
         (ITranslator<STE, TTE, SE, TE, ?, ?>) remaining.pop();
     final IProgramExecution<TTE, TE> translated =
         translator.translateProgramExecution(programExecution);
     return translateProgramExecution(remaining, translated);
   }
 }
  @Override
  public <STE, SE> IProgramExecution<?, ?> translateProgramExecution(
      final IProgramExecution<STE, SE> programExecution) {
    final Stack<ITranslator<?, ?, ?, ?, ?, ?>> current = new Stack<ITranslator<?, ?, ?, ?, ?, ?>>();
    boolean canTranslate = false;
    for (final ITranslator<?, ?, ?, ?, ?, ?> trans : mTranslationSequence) {
      current.push(trans);
      if (trans
              .getSourceTraceElementClass()
              .isAssignableFrom(programExecution.getTraceElementClass())
          && trans
              .getSourceExpressionClass()
              .isAssignableFrom(programExecution.getExpressionClass())) {
        canTranslate = true;
      }
    }
    if (!canTranslate) {
      throw new IllegalArgumentException(
          "You cannot translate "
              + programExecution
              + " with this backtranslation service, as there is no compatible ITranslator available");
    }

    if (!current
            .peek()
            .getSourceTraceElementClass()
            .isAssignableFrom(programExecution.getTraceElementClass())
        || !current
            .peek()
            .getSourceExpressionClass()
            .isAssignableFrom(programExecution.getExpressionClass())) {
      throw new IllegalArgumentException(
          "You cannot translate "
              + programExecution
              + " with this backtranslation service, as the last ITranslator in this chain is not compatible");
    }
    return translateProgramExecution(current, programExecution);
  }
 private <STE> Stack<ITranslator<?, ?, ?, ?, ?, ?>> prepareTranslatorStack(
     final Class<STE> clazz) {
   final Stack<ITranslator<?, ?, ?, ?, ?, ?>> current = new Stack<ITranslator<?, ?, ?, ?, ?, ?>>();
   boolean canTranslate = false;
   for (final ITranslator<?, ?, ?, ?, ?, ?> trans : mTranslationSequence) {
     current.push(trans);
     if (trans.getSourceTraceElementClass().isAssignableFrom(clazz)) {
       canTranslate = true;
     }
   }
   if (!canTranslate) {
     throw new IllegalArgumentException(
         "You cannot translate "
             + clazz.getSimpleName()
             + " with this backtranslation service, as there is no compatible ITranslator available");
   }
   if (!current.peek().getSourceTraceElementClass().isAssignableFrom(clazz)) {
     throw new IllegalArgumentException(
         "You cannot translate "
             + clazz.getSimpleName()
             + " with this backtranslation service, as the last ITranslator in this chain is not compatible");
   }
   return current;
 }
 @SuppressWarnings("unchecked")
 private <TE> String translateExpressionToString(
     final TE expression, final ITranslator<?, ?, ?, ?, ?, ?> trans) {
   final ITranslator<?, ?, ?, TE, ?, ?> last = (ITranslator<?, ?, ?, TE, ?, ?>) trans;
   return last.targetExpressionToString(expression);
 }
 @SuppressWarnings("unchecked")
 private <TTE> List<String> translateTraceToString(
     final List<TTE> trace, final ITranslator<?, ?, ?, ?, ?, ?> trans) {
   final ITranslator<?, TTE, ?, ?, ?, ?> last = (ITranslator<?, TTE, ?, ?, ?, ?>) trans;
   return last.targetTraceToString(trace);
 }