/** Create singleton template for use with dictionary values */
 public ST createSingleton(Token templateToken) {
   String template;
   if (templateToken.getType() == GroupParser.BIGSTRING) {
     template = Misc.strip(templateToken.getText(), 2);
   } else {
     template = Misc.strip(templateToken.getText(), 1);
   }
   CompiledST impl = compile(getFileName(), null, null, template, templateToken);
   ST st = createStringTemplateInternally(impl);
   st.groupThatCreatedThisInstance = this;
   st.impl.hasFormalArgs = false;
   st.impl.name = ST.UNKNOWN_NAME;
   st.impl.defineImplicitlyDefinedTemplates(this);
   return st;
 }
  /**
   * Import template files, directories, and group files. Priority is given to templates defined in
   * the current group; this, in effect, provides inheritance. Polymorphism is in effect so that if
   * an inherited template references template t() then we search for t() in the subgroup first.
   *
   * <p>If you specify an absolute file name or directory name, the import statement uses that
   * directly. If it is not an absolute path, we look that entity up in the directory holding the
   * group that initiates the import. If file or directory is not in that directory, then we load
   * using the classpath.
   *
   * <p>Templates are loaded on-demand from import dirs. Imported groups are loaded on-demand when
   * searching for a template.
   *
   * <p>The listener of this group is passed to the import group so errors found while loading
   * imported element are sent to listener of this group.
   */
  public void importTemplates(Token fileNameToken) {
    String fileName = fileNameToken.getText();
    // do nothing upon syntax error
    if (fileName == null || fileName.equals("<missing STRING>")) return;
    fileName = Misc.strip(fileName, 1);

    // System.out.println("import "+fileName);
    boolean isGroupFile = fileName.endsWith(".stg");
    boolean isTemplateFile = fileName.endsWith(".st");
    boolean isGroupDir = !(isGroupFile || isTemplateFile);

    STGroup g = null;

    File f = new File(fileName);
    if (f.isAbsolute()) { // load directly if absolute
      if (isTemplateFile) {
        g = new STGroup();
        g.setListener(this.getListener());
        g.loadAbsoluteTemplateFile(fileName);
      } else if (isGroupFile) {
        g = new STGroupFile(fileName, delimiterStartChar, delimiterStopChar);
        g.setListener(this.getListener());
      } else if (isGroupDir) {
        g = new STGroupDir(fileName, delimiterStartChar, delimiterStopChar);
        g.setListener(this.getListener());
      }
      importTemplates(g);
      return;
    }

    // it's a relative name; search path is working dir, g.stg's dir, CLASSPATH
    URL thisRoot = getRootDirURL();
    URL fileUnderRoot = null;
    //		System.out.println("thisRoot="+thisRoot);
    try {
      fileUnderRoot = new URL(thisRoot + "/" + fileName);
    } catch (MalformedURLException mfe) {
      errMgr.internalError(null, "can't build URL for " + thisRoot + "/" + fileName, mfe);
      return;
    }
    if (isTemplateFile) {
      g = new STGroup();
      g.setListener(this.getListener());
      URL fileURL;
      if (Misc.urlExists(fileUnderRoot)) fileURL = fileUnderRoot;
      else fileURL = getURL(fileName); // try CLASSPATH
      if (fileURL != null) {
        try {
          InputStream s = fileURL.openStream();
          ANTLRInputStream templateStream = new ANTLRInputStream(s);
          templateStream.name = fileName;
          CompiledST code = g.loadTemplateFile("", fileName, templateStream);
          if (code == null) g = null;
        } catch (IOException ioe) {
          errMgr.internalError(null, "can't read from " + fileURL, ioe);
          g = null;
        }
      } else {
        g = null;
      }
    } else if (isGroupFile) {
      // System.out.println("look for fileUnderRoot: "+fileUnderRoot);
      if (Misc.urlExists(fileUnderRoot)) {
        g = new STGroupFile(fileUnderRoot, encoding, delimiterStartChar, delimiterStopChar);
        g.setListener(this.getListener());
      } else {
        g = new STGroupFile(fileName, delimiterStartChar, delimiterStopChar);
        g.setListener(this.getListener());
      }
    } else if (isGroupDir) {
      //			System.out.println("try dir "+fileUnderRoot);
      if (Misc.urlExists(fileUnderRoot)) {
        g = new STGroupDir(fileUnderRoot, encoding, delimiterStartChar, delimiterStopChar);
        g.setListener(this.getListener());
      } else {
        // try in CLASSPATH
        //				System.out.println("try dir in CLASSPATH "+fileName);
        g = new STGroupDir(fileName, delimiterStartChar, delimiterStopChar);
        g.setListener(this.getListener());
      }
    }

    if (g == null) {
      errMgr.compileTimeError(ErrorType.CANT_IMPORT, null, fileNameToken, fileName);
    } else {
      importTemplates(g);
    }
  }