All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.appland.appmap.cli.Init Maven / Gradle / Ivy

package com.appland.appmap.cli;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.SerializerFeature;
import picocli.CommandLine;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.function.Consumer;

@CommandLine.Command(name = "init", description = "Suggests AppMap configuration settings for a new project.")
public class Init implements Callable {
  @CommandLine.ParentCommand
  private CLI parent;

  static class Configuration {
    @JSONField
    public String filename;

    @JSONField
    public String contents;
  }

  static class Result {
    @JSONField
    public Configuration configuration;
  }

  public Integer call() throws Exception {
    System.err.printf("Init AppMap project configuration in directory: %s\n", parent.directory);

    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    pw.println("# This is the AppMap configuration file.");
    pw.println("# For full documentation of this file for Java programs, see:");
    pw.println("# https://appland.com/docs/reference/appmap-java.html#configuration");
    pw.format("name: %s\n", CLI.projectName(new File(parent.directory)));

    // For now, this only works in this type of standardize repo structure.
    File javaDir = Paths.get(parent.directory).resolve("src/main/java").toFile();
    if (javaDir.isDirectory()) {
      // Collect package names in src/main/java
      Set packages = new HashSet<>();
      Files.walkFileTree(javaDir.toPath(), new SimpleFileVisitor() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
          if (file.getFileName().toString().endsWith(".java")) {
            Path packagePath = file.getParent().subpath(javaDir.toPath().getNameCount(), file.getParent().getNameCount());
            if (packagePath.getNameCount() > 0) {
              packages.add(packagePath);
            }
          }
          return FileVisitResult.CONTINUE;
        }
      });

      pw.println("# Your project contains the directory src/main/java.");
      pw.println("# AppMap has auto-detected the following Java packages in this directory:");
      pw.println("packages:");
      // Collect just the packages that don't have a matching ancestor in the package list.
      List topLevelPackages = packages.stream().sorted().collect(ArrayList::new, (memo, packagePath) -> {
        for (int i = 1; i < packagePath.getNameCount(); i++) {
          Path ancestorPath = packagePath.subpath(0, i);
          if (memo.contains(ancestorPath)) {
            return;
          }
        }
        memo.add(packagePath);
      }, ArrayList::addAll);
      topLevelPackages.forEach(new Consumer() {
        @Override
        public void accept(Path packagePath) {
          List tokens = new ArrayList<>();
          for (int i = 0; i < packagePath.getNameCount(); i++) {
            tokens.add(packagePath.getName(i).toString());
          }
          String path = String.join(".", tokens);
          pw.format("- path: %s\n", path);
        }
      });
    } else {
      pw.println("packages: []");
      pw.println("# appmap-java init looks for source packages in src/main/java.");
      pw.println("# This folder was not found in your project, so no packages were auto-detected.");
      pw.println("# You can add your source packages by replacing the line above with lines like this:");
      pw.println("# packages:");
      pw.println("# - path: com.mycorp.pkg");
      pw.println("# - path: org.otherstuff.pkg");
    }

    Configuration configuration = new Configuration();
    configuration.filename = "appmap.yml";
    configuration.contents = sw.toString();
    Result result = new Result();
    result.configuration = configuration;

    parent.getOutputStream().println(JSON.toJSONString(result, SerializerFeature.PrettyFormat));

    return 0;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy