package org.jboss.windup.graph.service; import org.apache.commons.lang.RandomStringUtils; import org.jboss.windup.graph.GraphContext; import org.jboss.windup.graph.model.ProjectModel; import org.jboss.windup.graph.model.WindupConfigurationModel; import org.jboss.windup.graph.model.resource.FileModel; import org.jboss.windup.graph.traversal.OnlyOnceTraversalStrategy; import org.jboss.windup.graph.traversal.ProjectModelTraversal; import org.jboss.windup.util.PathUtil; import java.nio.file.Path; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.StreamSupport; /** * Provides useful methods for querying, creating, and updating {@link ProjectModel} instances. */ public class ProjectService extends GraphService<ProjectModel> { public static final String SHARED_LIBS_UNIQUE_ID = "<shared-libs>"; public static final String SHARED_LIBS_APP_NAME = "Archives shared by multiple applications"; public static final String SHARED_LIBS_FILENAME = "shared-libs"; public ProjectService(GraphContext context) { super(context, ProjectModel.class); } /** * Gets a {@link ProjectModel} with the given name. */ public ProjectModel getByName(String name) { return getUnique(getTypedQuery().has(ProjectModel.NAME, name)); } public ProjectModel getByUniqueID(String id) { return getUnique(getTypedQuery().has(ProjectModel.UNIQUE_ID, id)); } /** * Gets the project model used for shared libraries (libraries duplicated in multiple places within one or * more applications). */ public ProjectModel getOrCreateSharedLibsProject() { ProjectService service = new ProjectService(getGraphContext()); ProjectModel sharedLibsProject = service.getByUniqueID(SHARED_LIBS_UNIQUE_ID); if (sharedLibsProject == null) { sharedLibsProject = service.create(); sharedLibsProject.setName(SHARED_LIBS_APP_NAME); sharedLibsProject.setUniqueID(SHARED_LIBS_UNIQUE_ID); sharedLibsProject.setProjectType(ProjectModel.TYPE_VIRTUAL); // attach a directory to it, as we generally assume that all projects have a location on disk Path archivesDirectory = WindupConfigurationService.getArchivesPath(getGraphContext()); Path sharedLibsPath = archivesDirectory.resolve("shared-libs-" + RandomStringUtils.randomAlphabetic(6)).resolve(SHARED_LIBS_FILENAME); PathUtil.createDirectory(sharedLibsPath, "shared libs virtual app"); FileModel sharedLibsFileModel = new FileService(getGraphContext()).createByFilePath(sharedLibsPath.toString()); sharedLibsProject.setRootFileModel(sharedLibsFileModel); sharedLibsProject.addFileModel(sharedLibsFileModel); // attach this to the configuration, so that reporting treats it as a standalone app WindupConfigurationModel configuration = WindupConfigurationService.getConfigurationModel(getGraphContext()); configuration.addInputPath(sharedLibsFileModel); } return sharedLibsProject; } public Map<ProjectModel, ProjectModel> getProjectToRootProjectMap() { Map<ProjectModel, ProjectModel> projectModels = new HashMap<>(); for (FileModel inputPath : WindupConfigurationService.getConfigurationModel(this.getGraphContext()).getInputPaths()) { ProjectModel rootProjectModel = inputPath.getProjectModel(); if (rootProjectModel == null) { continue; } ProjectModelTraversal traversal = new ProjectModelTraversal(rootProjectModel); traversal.getAllProjects(true).forEach(subProject -> projectModels.put(subProject, rootProjectModel)); } return projectModels; } public Set<ProjectModel> getFilteredProjectModels(Collection<String> selectedPaths) { Set<ProjectModel> projectModels = new HashSet<>(); if (selectedPaths.isEmpty()) { return projectModels; } for (FileModel inputPath : WindupConfigurationService.getConfigurationModel(this.getGraphContext()).getInputPaths()) { String filePath = inputPath.getFilePath(); if (selectedPaths.contains(filePath)) { ProjectModel rootProjectModel = inputPath.getProjectModel(); if (rootProjectModel == null) { continue; } ProjectModelTraversal traversal = new ProjectModelTraversal(rootProjectModel); projectModels.addAll(traversal.getAllProjects(true)); } } return projectModels; } public Set<ProjectModel> getRootProjectModels() { Iterable<FileModel> fileModelIterable = WindupConfigurationService.getConfigurationModel(this.getGraphContext()).getInputPaths(); return StreamSupport.stream(fileModelIterable.spliterator(), false) .map(FileModel::getProjectModel) .filter(Objects::nonNull) .collect(Collectors.toSet()); } }