content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.camel.springboot.maven;
  
  import java.io.File;
  import java.io.IOException;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.util.List;
  import java.util.stream.Collectors;
  import java.util.stream.Stream;
  import org.apache.commons.io.FileUtils;
  import org.apache.maven.plugin.AbstractMojo;
  import org.apache.maven.plugin.MojoExecutionException;
  import org.apache.maven.plugin.MojoFailureException;
  import org.apache.maven.plugins.annotations.LifecyclePhase;
  import org.apache.maven.plugins.annotations.Mojo;
  import org.apache.maven.plugins.annotations.Parameter;
  import org.apache.maven.project.MavenProject;
  import org.apache.maven.repository.RepositorySystem;
  
  import javax.inject.Inject;
  
  @Mojo(name = "generate-starter", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_RESOURCES)
  public class StarterGeneratorMojo extends AbstractMojo {
  
      /**
       * Used to look up Artifacts in the remote repository.
       */
      @Inject
      protected RepositorySystem artifactFactory;
  
      /**
       * The maven project.
       */
      @Parameter(defaultValue = "${project}", readonly = true)
      protected MavenProject project;
  
      /**
       * The source pom template file.
       */
      @Parameter(defaultValue = "${basedir}/template-starter-pom.xml")
      protected File sourcePom;
  
      @Parameter(defaultValue = "${basedir}/../../components-starter")
      protected File startersDir;
  
      @Parameter(property = "action", required = true)
      protected String action;
  
      @Parameter(property = "componentName", required = true)
      protected String componentName;
  
      @Override
      public void execute() throws MojoExecutionException, MojoFailureException {
          if (!"create".equals(action) && !"delete".equals(action))
              throw new MojoFailureException("Unknown action: " + action);
          if (componentName == null || componentName.isEmpty())
              throw new MojoFailureException("Starter name must be specified as the parameter");
          if (componentName.startsWith("camel-"))
              componentName = componentName.substring("camel-".length());
          if (componentName.endsWith("-starter"))
              componentName = componentName.substring(0, componentName.length() - "-starter".length());
          try {
              doExecute();
          } catch (MojoExecutionException | MojoFailureException e) {
              throw e;
          } catch (Exception e) {
              throw new MojoExecutionException("Unable to " + action + " starter " + componentName, e);
          }
      }
  
      protected void doExecute() throws Exception {
          switch (action) {
          case "create":
              createStarter();
              break;
          case "delete":
              deleteStarter();
              break;
          }
      }
  
      private void deleteStarter() throws MojoFailureException, IOException {
          getLog().info("Deleting starter for " + componentName);
          File directory = new File(startersDir, "camel-" + componentName + "-starter");
          if (!directory.exists()) {
              throw new MojoFailureException("Starter does not exist: " + componentName);
          }
          FileUtils.deleteDirectory(directory);
          Path parent = new File(startersDir, "pom.xml").toPath();
          List<String> lines = Files.readAllLines(parent);
          int modulesStart = -1, modulesEnd = -1;
          for (int i = 0; i < lines.size(); i++) {
              String s = lines.get(i);
              if (s.contains("<modules>"))
                  modulesStart = i + 1;
              else if (s.contains("</modules>"))
                  modulesEnd = i;
          }
          lines = concat(lines.subList(0, modulesStart).stream(),
                  lines.subList(modulesStart, modulesEnd).stream()
                          .filter(s -> !s.contains("<module>camel-" + componentName + "-starter</module>")),
                  lines.subList(modulesEnd, lines.size()).stream()).collect(Collectors.toList());
          Files.write(parent, lines);
      }
  
      private void createStarter() throws MojoFailureException, IOException {
          getLog().info("Creating starter for " + componentName);
          File directory = new File(startersDir, "camel-" + componentName + "-starter");
          if (directory.exists()) {
              if (directory.isDirectory()) {
                  throw new MojoFailureException("Directory already exists: " + directory);
              } else {
                  throw new MojoFailureException("Can not create directory as a file already exists: " + directory);
              }
          }
          if (!directory.mkdirs()) {
              throw new MojoFailureException("Unable to create directory: " + directory);
          }
          Files.write(new File(directory, "pom.xml").toPath(), Files.lines(sourcePom.toPath())
                  .map(s -> s.replaceAll("%NAME%", componentName)).collect(Collectors.toList()));
          Path parent = new File(startersDir, "pom.xml").toPath();
          List<String> lines = Files.readAllLines(parent);
          int modulesStart = -1, modulesEnd = -1;
          for (int i = 0; i < lines.size(); i++) {
              String s = lines.get(i);
              if (s.contains("<modules>"))
                  modulesStart = i + 1;
              else if (s.contains("</modules>"))
                  modulesEnd = i;
          }
          lines = concat(lines.subList(0, modulesStart).stream(),
                  Stream.concat(lines.subList(modulesStart, modulesEnd).stream(),
                          Stream.of("    <module>camel-" + componentName + "-starter</module>")).sorted().distinct(),
                  lines.subList(modulesEnd, lines.size()).stream()).collect(Collectors.toList());
          Files.write(parent, lines);
      }
  
      private static <T> Stream<T> concat(Stream<T> s1, Stream<T> s2, Stream<T> s3) {
          return Stream.concat(s1, Stream.concat(s2, s3));
      }
  
  }
  