public static @NotNull PsiElement createFromTemplate(final @NotNull FileTemplate template,
                                                       @Nullable String fileName,
                                                       @Nullable Map<String, Object> propsMap,
                                                       final @NotNull PsiDirectory directory,
                                                       @Nullable ClassLoader classLoader) throws Exception {
    Project project = directory.getProject();
    FileTemplateManager.getInstance(project).addRecentName(template.getName());

    if (propsMap == null) {
      Properties p = FileTemplateManager.getInstance(project).getDefaultProperties();
      propsMap = new HashMap<>();
      putAll(propsMap, p);
    }

    Properties p = new Properties();
    fillDefaultProperties(p, directory);
    putAll(propsMap, p);

    final CreateFromTemplateHandler handler = findHandler(template);
    if (fileName != null && propsMap.get(FileTemplate.ATTRIBUTE_NAME) == null) {
      propsMap.put(FileTemplate.ATTRIBUTE_NAME, fileName);
    }
    else if (fileName == null && handler.isNameRequired()) {
      fileName = (String)propsMap.get(FileTemplate.ATTRIBUTE_NAME);
      if (fileName == null) {
        throw new Exception("File name must be specified");
      }
    }
    String fileNameWithExt = fileName + (StringUtil.isEmpty(template.getExtension()) ? "" : "." + template.getExtension());
    propsMap.put(FileTemplate.ATTRIBUTE_FILE_NAME, fileNameWithExt);
    propsMap.put(FileTemplate.ATTRIBUTE_FILE_PATH, FileUtil.join(directory.getVirtualFile().getPath(), fileNameWithExt));
    String dirPath = getDirPathRelativeToProjectBaseDir(directory);
    if (dirPath != null) {
      propsMap.put(FileTemplate.ATTRIBUTE_DIR_PATH, dirPath);
    }

    //Set escaped references to dummy values to remove leading "\" (if not already explicitly set)
    String[] dummyRefs = calculateAttributes(template.getText(), propsMap, true, directory.getProject());
    for (String dummyRef : dummyRefs) {
      propsMap.put(dummyRef, "");
    }

    handler.prepareProperties(propsMap, fileName, template, project);
    handler.prepareProperties(propsMap);

    Map<String, Object> props_ = propsMap;
    String fileName_ = fileName;
    String mergedText = ClassLoaderUtil.computeWithClassLoader(
      classLoader != null ? classLoader : FileTemplateUtil.class.getClassLoader(),
      () -> template.getText(props_));
    String templateText = StringUtil.convertLineSeparators(mergedText);

    if (LightVirtualFile.shouldSkipEventSystem(directory.getVirtualFile())) {
      return handler.createFromTemplate(project, directory, fileName_, template, templateText, props_);
    }

    return WriteCommandAction
      .writeCommandAction(project)
      .withName(handler.commandName(template))
      .compute(() -> handler.createFromTemplate(project, directory, fileName_, template, templateText, props_));
  }
public static @NotNull PsiElement createFromTemplate(final @NotNull FileTemplate template,
                                                       @Nullable String fileName,
                                                       @Nullable Map<String, Object> propsMap,
                                                       final @NotNull PsiDirectory directory,
                                                       @Nullable ClassLoader classLoader)