@Override
    public void execute(final Object message) throws Exception {
      if (logger.isInfoEnabled()) {
        logger.info("UssdInterpreter Processing INFO request");
      }
      final NotificationsDao notifications = storage.getNotificationsDao();
      SipServletRequest info = (SipServletRequest) message;

      SipServletResponse okay = info.createResponse(200);
      okay.send();

      UssdInfoRequest ussdInfoRequest = new UssdInfoRequest(info);
      String ussdText = ussdInfoRequest.getMessage();
      if (ussdCollectAction != null && !ussdCollectAction.isEmpty() && ussdText != null) {
        URI target = null;
        try {
          target = URI.create(ussdCollectAction);
        } catch (final Exception exception) {
          final Notification notification =
              notification(ERROR_NOTIFICATION, 11100, ussdCollectAction + " is an invalid URI.");
          notifications.addNotification(notification);
          sendMail(notification);
          final StopInterpreter stop = new StopInterpreter();
          source.tell(stop, source);
          return;
        }
        final URI base = request.getUri();
        final URI uri = UriUtils.resolve(base, target);
        // Parse "method".
        String method = "POST";
        Attribute attribute = null;
        try {
          attribute = verb.attribute("method");
        } catch (Exception e) {
        }
        if (attribute != null) {
          method = attribute.value();
          if (method != null && !method.isEmpty()) {
            if (!"GET".equalsIgnoreCase(method) && !"POST".equalsIgnoreCase(method)) {
              final Notification notification =
                  notification(
                      WARNING_NOTIFICATION,
                      14104,
                      method + " is not a valid HTTP method for <Gather>");
              notifications.addNotification(notification);
              method = "POST";
            }
          } else {
            method = "POST";
          }
        }

        final List<NameValuePair> parameters = parameters();
        parameters.add(new BasicNameValuePair("Digits", ussdText));
        request = new HttpRequestDescriptor(uri, method, parameters);
        downloader.tell(request, source);
        ussdCollectTag = null;
        ussdLanguageTag = null;
        ussdMessageTags = new LinkedBlockingQueue<Tag>();
        return;
      } else if (ussdInfoRequest
          .getUssdMessageType()
          .equals(UssdMessageType.unstructuredSSNotify_Response)) {
        UssdRestcommResponse ussdRestcommResponse = new UssdRestcommResponse();
        ussdRestcommResponse.setErrorCode("1");
        ussdRestcommResponse.setIsFinalMessage(true);
        ussdCall.tell(ussdRestcommResponse, source);
        return;
      }
      // Ask the parser for the next action to take.
      final GetNextVerb next = GetNextVerb.instance();
      parser.tell(next, self());
    }
    @Override
    public void execute(final Object message) throws Exception {
      if (logger.isInfoEnabled()) {
        logger.info("Preparing the USSD Message");
      }
      if (End.class.equals(message.getClass())) {

        Boolean hasCollect = false;
        UssdRestcommResponse ussdRestcommResponse = new UssdRestcommResponse();

        String language = "";
        if (ussdLanguageTag == null) {
          language = "en";
          ussdRestcommResponse.setLanguage(language);
        } else {
          language = ussdLanguageTag.text();
          ussdRestcommResponse.setLanguage(language);
        }

        if (language.equalsIgnoreCase("en")) {
          maxMessageLength = englishLength;
          ussdRestcommResponse.setMessageLength(englishLength);
        } else {
          maxMessageLength = nonEnglishLength;
          ussdRestcommResponse.setMessageLength(nonEnglishLength);
        }

        StringBuffer ussdText = processUssdMessageTags(ussdMessageTags);

        if (ussdCollectTag != null) {
          hasCollect = true;
          ussdCollectAction = ussdCollectTag.attribute("action").value();
          ussdRestcommResponse.setUssdCollectAction(ussdCollectAction);
          Queue<Tag> children =
              new java.util.concurrent.ConcurrentLinkedQueue<Tag>(ussdCollectTag.children());
          if (children != null && children.size() > 0) {
            ussdText.append(processUssdMessageTags(children));
          } else if (ussdCollectTag.text() != null) {
            ussdText.append(ussdCollectTag.text());
          }
        }

        if (ussdText.length() > maxMessageLength) {
          final String errorString =
              "Error while preparing the USSD response. Ussd text length more "
                  + "than the permitted for the selected language: "
                  + maxMessageLength;
          Notification notification = notification(ERROR_NOTIFICATION, 11100, errorString);
          if (notification != null) {
            final NotificationsDao notifications = storage.getNotificationsDao();
            notifications.addNotification(notification);
            sendMail(notification);
          }
          if (logger.isInfoEnabled()) {
            logger.info(errorString);
          }
          ussdText = new StringBuffer();
          ussdText.append(
              "Error while preparing the response.\nMessage length exceeds the maximum.");
        }

        ussdRestcommResponse.setMessage(ussdText.toString());

        if (logger.isInfoEnabled()) {
          logger.info("UssdMessage prepared, hasCollect: " + hasCollect);
          logger.info(
              "UssdMessage prepared: " + ussdMessage.toString() + " hasCollect: " + hasCollect);
        }

        if (callInfo.direction().equalsIgnoreCase("inbound")) {
          // USSD PULL
          if (hasCollect) {
            ussdRestcommResponse.setMessageType(UssdMessageType.unstructuredSSRequest_Request);
            ussdRestcommResponse.setIsFinalMessage(false);
          } else {
            ussdRestcommResponse.setMessageType(
                UssdMessageType.processUnstructuredSSRequest_Response);
            ussdRestcommResponse.setIsFinalMessage(true);
          }
        } else {
          // USSD PUSH
          if (hasCollect) {
            ussdRestcommResponse.setMessageType(UssdMessageType.unstructuredSSRequest_Request);
            ussdRestcommResponse.setIsFinalMessage(false);
          } else {
            ussdRestcommResponse.setMessageType(UssdMessageType.unstructuredSSNotify_Request);
            if (ussdRestcommResponse.getErrorCode() != null) {
              ussdRestcommResponse.setIsFinalMessage(true);
            } else {
              ussdRestcommResponse.setIsFinalMessage(false);
            }
          }
        }
        if (logger.isInfoEnabled()) {
          logger.info("UssdRestcommResponse message prepared: " + ussdRestcommResponse);
        }
        ussdCall.tell(ussdRestcommResponse, source);
      }
    }