protected AccessLogValveAccessLogElement getClientToServerElement(
     ExtendedAccessLogValvePatternTokenizer tokenizer) throws IOException {
   if (tokenizer.hasSubToken()) {
     String token = tokenizer.getToken();
     if ("method".equals(token)) {
       return new AccessLogValveMethodElement();
     } else if ("uri".equals(token)) {
       if (tokenizer.hasSubToken()) {
         token = tokenizer.getToken();
         if ("stem".equals(token)) {
           return new AccessLogValveRequestURIElement();
         } else if ("query".equals(token)) {
           return new AccessLogValveAccessLogElement() {
             @Override
             public void addElement(
                 StringBuilder buf, Date date, Request request, Response response, long time) {
               String query = request.getQueryString();
               if (query != null) {
                 buf.append(query);
               } else {
                 buf.append('-');
               }
             }
           };
         }
       } else {
         return new AccessLogValveAccessLogElement() {
           @Override
           public void addElement(
               StringBuilder buf, Date date, Request request, Response response, long time) {
             String query = request.getQueryString();
             if (query == null) {
               buf.append(request.getRequestURI());
             } else {
               buf.append(request.getRequestURI());
               buf.append('?');
               buf.append(request.getQueryString());
             }
           }
         };
       }
     }
   } else if (tokenizer.hasParameter()) {
     String parameter = tokenizer.getParameter();
     if (parameter == null) {
       log.error("No closing ) found for in decode");
       return null;
     }
     return new ExtendedAccessLogValveRequestHeaderElement(this, parameter);
   }
   log.error("The next characters couldn't be decoded: " + tokenizer.getRemains());
   return null;
 }
 protected AccessLogValveAccessLogElement getProxyElement(
     ExtendedAccessLogValvePatternTokenizer tokenizer) throws IOException {
   String token = null;
   if (tokenizer.hasSubToken()) {
     tokenizer.getToken();
     return new AccessLogValveStringElement("-");
   } else if (tokenizer.hasParameter()) {
     tokenizer.getParameter();
     return new AccessLogValveStringElement("-");
   }
   log.error("The next characters couldn't be decoded: " + token);
   return null;
 }
 protected AccessLogValveAccessLogElement getServerToClientElement(
     ExtendedAccessLogValvePatternTokenizer tokenizer) throws IOException {
   if (tokenizer.hasSubToken()) {
     String token = tokenizer.getToken();
     if ("status".equals(token)) {
       return new AccessLogValveLocalPortElement(this);
     } else if ("comment".equals(token)) {
       return new AccessLogValveStringElement("?");
     }
   } else if (tokenizer.hasParameter()) {
     String parameter = tokenizer.getParameter();
     if (parameter == null) {
       log.error("No closing ) found for in decode");
       return null;
     }
     return new ExtendedAccessLogValveResponseHeaderElement(this, parameter);
   }
   log.error("The next characters couldn't be decoded: " + tokenizer.getRemains());
   return null;
 }
  protected AccessLogValveAccessLogElement getXParameterElement(
      ExtendedAccessLogValvePatternTokenizer tokenizer) throws IOException {
    if (!tokenizer.hasSubToken()) {
      log.error("x param in wrong format. Needs to be 'x-#(...)' read the docs!");
      return null;
    }
    String token = tokenizer.getToken();
    if ("threadname".equals(token)) {
      return new AccessLogValveThreadNameElement();
    }

    if (!tokenizer.hasParameter()) {
      log.error("x param in wrong format. Needs to be 'x-#(...)' read the docs!");
      return null;
    }
    String parameter = tokenizer.getParameter();
    if (parameter == null) {
      log.error("No closing ) found for in decode");
      return null;
    }
    if ("A".equals(token)) {
      return new ExtendedAccessLogValveServletContextElement(this, parameter);
    } else if ("C".equals(token)) {
      return new ExtendedAccessLogValveCookieElement(this, parameter);
    } else if ("R".equals(token)) {
      return new ExtendedAccessLogValveRequestAttributeElement(this, parameter);
    } else if ("S".equals(token)) {
      return new ExtendedAccessLogValveSessionAttributeElement(this, parameter);
    } else if ("H".equals(token)) {
      return getServletRequestElement(parameter);
    } else if ("P".equals(token)) {
      return new ExtendedAccessLogValveRequestParameterElement(this, parameter);
    } else if ("O".equals(token)) {
      return new ExtendedAccessLogValveResponseAllHeaderElement(this, parameter);
    }
    log.error("x param for servlet request, couldn't decode value: " + token);
    return null;
  }