docs: private static String lineExpand(String keyString, Map properties) {
  
          //System.out.println("DEBUG : expand(String, Properties), keyString: " + keyString);
  
          //if ("".equals(keyString))
          //throw new Exception("empty key string");
  
          if (resolvesToLiteral(keyString)) {
              //System.out.println("DEBUG : keyString: " + keyString + " is a literal");
              return keyString;
          }
          //System.out.println("DEBUG : expand(String, Properties), keyString: " + keyString + " does not resolve to literal");
  
          // look for ${<propName>}'s
          StringTokenizer keyStringTokenizer = new StringTokenizer(keyString, "${}", true);
  
          // return buffer
          StringBuffer sb = new StringBuffer();
  
          if (keyStringTokenizer.countTokens() == 1) {
              // we are done here since there is nothing but the final to be expanded string (no real
              // parsing necessary.
  
  
              //String rtnString = (String)properties.get(keyString);
              //if (null == rtnString)
  
              if (!properties.containsKey(keyString)) {
                  //System.out.println("unresolved property key : " + keyString);
                  return "";
              }
              return (String) properties.get(keyString);
  
              //throw new Exception("value for property: " + keyString + " is null");
              //System.out.println("quick and dirty, returning: " + rtnString);
              //return rtnString;
          }
  
  
          // set all token indicators to false
          boolean dollar = false;
          boolean lp = false;
          boolean rp = false;
  
  
          while (keyStringTokenizer.hasMoreTokens()) {
              //System.out.println("got a token");
  
              // the token matching <propName> in ${<propName>}
              String expTok;
  
              // seen all tokens, so reset them for next occurrance
              if (dollar == true && lp == true && rp == true) {
                  dollar = false;
                  lp = false;
                  rp = false;
              }
  
              // get next token based on any of $, {, } characters
              String tok = keyStringTokenizer.nextToken();
  
              // all token indicators false, means we have a passthru token, so just append to return buffer
              if (dollar == false && lp == false && rp == false) {
                  if (!tok.equals("$")) {
                      sb.append(tok);
                  }
              }
  
              // seen ${, but not } => we should have a token here to expand
              if (dollar == true && lp == true && rp == false) {
                  // the prop to expand
                  if (!tok.equals("}")) {
                      expTok = tok;
                      // append getProperty result of expTok
                      String expVal = (String) properties.get(expTok);
                      if (expVal == null) {
                          //throw new Exception("token expTok " + expTok + " is null");
                          //System.out.println("token expTok \"" + expTok + "\" is null");
                          sb.append("${").append(expTok).append("}");
                      }else{
                          sb.append(expVal);
                      }
                  } else {
                      // the } token is now encountered
                      rp = true;
                      continue;
                  }
              }
  
              // ensure we don't see $$, {$, }$
              if (tok.equals("$")) {
                  if (dollar == true) {
                      //throw new Exception("parsing error: $$ invalid");
                      throw new PropertyUtilException("parsing error: $$ invalid");
                  }
                  if (lp == true) {
                      //throw new Exception("parsing error: {$ invalid");
                      throw new PropertyUtilException("parsing error: {$ invalid");
                  }
                  if (rp == true) {
                      //throw new Exception("parsing error: }$ invalid");
                      throw new PropertyUtilException("parsing error: }$ invalid");
                  }
                  dollar = true;
                  continue;
              }
  
              // ensure $ is before {, and no {{ or }{
              if (tok.equals("{")) {
                  if (dollar == false) {
                      //throw new Exception("parsing error: $ symbol must occur before { symbol");
                      throw new PropertyUtilException("parsing error: $ symbol must occur before { symbol");
                  }
                  if (lp == true) {
                      //throw new Exception("parsing error: {{ invalid");
                      throw new PropertyUtilException("parsing error: {{ invalid");
                  }
                  if (rp == true) {
                      //throw new Exception("parsing error: }{ invalid");
                      throw new PropertyUtilException("parsing error: }{ invalid");
                  }
                  lp = true;
                  continue;
              }
  
              // ensure ${ is before }, and no }{
              if (tok.equals("}")) {
                  if (dollar == false) {
                      //throw new Exception("parsing error: $ symbol must occur before } symbol");
                      throw new PropertyUtilException("parsing error: $ symbol must occur before } symbol");
                  }
                  if (lp == false) {
                      //throw new Exception("parsing error: { symbol must occur before } symbol");
                      throw new PropertyUtilException("parsing error: { symbol must occur before } symbol");
                  }
                  if (rp == true) {
                      //throw new Exception("parsing error: }} invalid");
                      throw new PropertyUtilException("parsing error: }} invalid");
                  }
                  rp = true;
                  continue;
              }
  
          }
  
          if (null == sb.toString() || "".equals(sb.toString()))
          //throw new Exception("null string return:" + keyString);
              throw new PropertyUtilException("null string return:" + keyString);
  
          //System.out.println("PropertyUtil.expand(), returning: " + sb.toString());
          return sb.toString();
  
      }