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

com.nordstrom.common.file.PathUtils Maven / Gradle / Ivy

package com.nordstrom.common.file;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;

/**
 * This utility class provides a {@link #getNextPath(Path, String, String) getNextPath} method to acquire the next file
 * path in sequence for the specified base name and extension in the indicated target folder.  If the target folder
 * already contains at least one file that matches the specified base name and extension, the algorithm used to select
 * the next path will always return a path whose index is one more than the highest index that currently exists. (If a
 * single file with no index is found, its implied index is 0.)
 * 

* Example usage of {@code getNextPath} *
 *     ...
 *     
 *     /*
 *      * This example gets the next path in sequence for base name `artifact`
 *      * and extension `txt` in the TestNG output directory.
 *      * 
 *      * For purposes of this example, the output directory already contains 
 *      * the following files: `artifact.txt`, `artifact-3.txt`
 *      */
 * 
 *     Path collectionPath = Paths.get(testContext.getOutputDirectory());
 *     // => C:\git\my-project\test-output\Default suite
 * 
 *     Path artifactPath;
 *     try {
 *         artifactPath = PathUtils.getNextPath(collectionPath, "artifact", "txt");
 *         // => C:\git\my-project\test-output\Default suite\artifact-4.txt
 *     } catch (IOException e) {
 *         provider.getLogger().info("Unable to get output path; no artifact was captured", e);
 *         return;
 *     }
 *     
 *     ...
 * 
*/ public final class PathUtils { private PathUtils() { throw new AssertionError("PathUtils is a static utility class that cannot be instantiated"); } private static final String SUREFIRE_PATH = "surefire-reports"; private static final String FAILSAFE_PATH = "failsafe-reports"; /** * This enumeration contains methods to help build proxy subclass names and select reports directories. */ public enum ReportsDirectory { SUREFIRE_1("(Test)(.*)", SUREFIRE_PATH), SUREFIRE_2("(.*)(Test)", SUREFIRE_PATH), SUREFIRE_3("(.*)(Tests)", SUREFIRE_PATH), SUREFIRE_4("(.*)(TestCase)", SUREFIRE_PATH), FAILSAFE_1("(IT)(.*)", FAILSAFE_PATH), FAILSAFE_2("(.*)(IT)", FAILSAFE_PATH), FAILSAFE_3("(.*)(ITCase)", FAILSAFE_PATH), ARTIFACT(".*", "artifact-capture"); private String regex; private String folder; ReportsDirectory(String regex, String folder) { this.regex = regex; this.folder = folder; } /** * Get the regular expression that matches class names for this constant. * * @return class-matching regular expression string */ public String getRegEx() { return regex; } /** * Get the name of the folder associated with this constant. * * @return class-related folder name */ public String getFolder() { return folder; } /** * Get the resolved Maven-derived path associated with this constant. * * @return Maven folder path */ public Path getPath() { return getTargetPath().resolve(folder); } /** * Get the reports directory constant for the specified test class object. * * @param obj test class object * @return reports directory constant */ public static ReportsDirectory fromObject(Object obj) { String name = obj.getClass().getSimpleName(); for (ReportsDirectory constant : values()) { if (name.matches(constant.regex)) { return constant; } } throw new IllegalStateException("Someone removed the 'default' pattern from this enumeration"); } /** * Get reports directory path for the specified test class object. * * @param obj test class object * @return reports directory path */ public static Path getPathForObject(Object obj) { ReportsDirectory constant = fromObject(obj); return getTargetPath().resolve(constant.folder); } /** * Get the path for the 'target' folder of the current project. * * @return path for project 'target' folder */ private static Path getTargetPath() { return Paths.get(getBaseDir(), "target"); } } /** * Get the next available path in sequence for the specified base name and extension in the specified folder. * * @param targetPath path to target directory for the next available path in sequence * @param baseName base name for the path sequence * @param extension extension for the path sequence * @return the next available path in sequence * @throws IOException if an I/O error is thrown when accessing the starting file. */ public static Path getNextPath(Path targetPath, String baseName, String extension) throws IOException { Objects.requireNonNull(targetPath, "[targetPath] must be non-null"); Objects.requireNonNull(baseName, "[baseName] must be non-null"); Objects.requireNonNull(extension, "[extension] must be non-null"); File targetFile = targetPath.toFile(); if ( ! (targetFile.exists() && targetFile.isDirectory())) { throw new IllegalArgumentException("[targetPath] must specify an existing directory"); } if (baseName.isEmpty()) { throw new IllegalArgumentException("[baseName] must specify a non-empty string"); } if (extension.isEmpty()) { throw new IllegalArgumentException("[extension] must specify a non-empty string"); } Visitor visitor = new Visitor(baseName, extension); Files.walkFileTree(targetPath, EnumSet.noneOf(FileVisitOption.class), 1, visitor); return targetPath.resolve(visitor.getNewName()); } /** * Get project base directory. * * @return project base directory */ public static String getBaseDir() { Path currentRelativePath = Paths.get(System.getProperty("user.dir")); return currentRelativePath.toAbsolutePath().toString(); } private static class Visitor implements FileVisitor { private String baseName; private String extension; private int base, ext; private PathMatcher pathMatcher; private List intList = new ArrayList<>(); Visitor(String baseName, String extension) { this.baseName = baseName; this.extension = extension; this.base = baseName.length(); this.ext = extension.length() + 1; this.pathMatcher = FileSystems.getDefault().getPathMatcher("regex:\\Q" + baseName + "\\E(-\\d+)?\\." + extension); } @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (attrs.isRegularFile() && pathMatcher.matches(file.getFileName())) { String name = file.getFileName().toString(); String iStr = "0" + name.substring(base, name.length() - ext); iStr = iStr.replace("0-", ""); intList.add(Integer.valueOf(iStr) + 1); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { return FileVisitResult.CONTINUE; } public String getNewName() { String newName; if (intList.isEmpty()) { newName = baseName + "." + extension; } else { Collections.sort(intList, Collections.reverseOrder()); newName = baseName + "-" + intList.get(0) + "." + extension; } return newName; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy