package org.jboss.windup.rules.apps.mavenize;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
import java.util.Collections;
import java.util.logging.Logger;
import org.jboss.windup.ast.java.data.TypeReferenceLocation;
import org.jboss.windup.graph.GraphContext;
import org.jboss.windup.graph.model.ProjectModel;
import org.jboss.windup.graph.service.Service;
import org.jboss.windup.rules.apps.java.archives.model.ArchiveCoordinateModel;
import org.jboss.windup.rules.apps.java.scan.ast.TypeInterestFactory;
import org.jboss.windup.util.Logging;
/**
* This is a service class that provides information about which artifacts contain the given package.
*
* @author <a href="http://ondra.zizka.cz/">Ondrej Zizka, zizka@seznam.cz</a>
*
* TODO: This could also be achived through WINDUP-1028, depends on what gets merged when.
*/
public class PackagesToContainingMavenArtifactsIndex
{
private static final Logger LOG = Logging.get(PackagesToContainingMavenArtifactsIndex.class);
public static final String EDGE_USES = "uses";
private final GraphContext graphContext;
public PackagesToContainingMavenArtifactsIndex(GraphContext graphContext)
{
this.graphContext = graphContext;
}
/**
* Which projects contain classes which reference the given package (in their imports).
*/
private Iterable<ProjectModel> getProjectsContainingClassesReferencingPackage(String pkg)
{
throw new UnsupportedOperationException("Not supported yet.");
}
/**
* For given API artifact, finds the projects whose Java classes use artifact's classes,
* and links them in the graph.
*
* TODO:
* Because the graph doesn't contain data about all Java classes,
* this will likely need to use TypeInterestFactory -
* register all the classes (or just packages?) from the API jars.
* This is executed in a separate rule.
*/
public void registerPackagesFromAPI(MavenCoord apiCoords)
{
Iterable<String> packages = this.getPackagesInArtifact(apiCoords);
for (String pkg : packages)
{
this.registerPackageInTypeInterestFactory(pkg);
}
}
/**
* After the packages are registered and Java scanning done,
* we can link the ProjectModel and API packages together.
* ProjectModel --uses--> ArchiveCoordinateModel
*/
public void markProjectsUsingPackagesFromAPI(MavenCoord apiCoords)
{
final Service<ArchiveCoordinateModel> coordsService = graphContext.service(ArchiveCoordinateModel.class);
Iterable<String> packages = this.getPackagesInArtifact(apiCoords);
for (String pkg : packages)
{
Iterable<ProjectModel> projects = this.getProjectsContainingClassesReferencingPackage(pkg);
for (ProjectModel project : projects)
{
ArchiveCoordinateModel apiArchiveRepresentant = new ArchiveCoordinateService(graphContext, ArchiveCoordinateModel.class)
.getSingleOrCreate(apiCoords.getGroupId(), apiCoords.getArtifactId(), null); // We specifically want null.
project.asVertex().addEdge(EDGE_USES, apiArchiveRepresentant.asVertex());
}
}
}
/**
* For given API artifact, finds the projects whose Java classes use artifact's classes,
* and links them in the graph.
*/
public boolean moduleContainsPackagesFromAPI(ProjectModel projectModel, MavenCoord apiCoords)
{
ArchiveCoordinateModel archive = new ArchiveCoordinateService(graphContext, ArchiveCoordinateModel.class).findSingle(apiCoords.getGroupId(), apiCoords.getArtifactId(), null);
if (archive == null)
return false;
//return graphContext.testIncidence(projectModel.asVertex(), archive.asVertex(), EDGE_USES);
Iterable<Vertex> projectsVerts = archive.asVertex().getVertices(Direction.IN, EDGE_USES);
Iterable<ProjectModel> projects = graphContext.getFramed().frameVertices(projectsVerts, ProjectModel.class);
for (ProjectModel project : projects)
{
if (projectModel.equals(project))
return true;
}
return false;
}
private Iterable<String> getPackagesInArtifact(MavenCoord apiCoords)
{
// TODO: WINDUP-1028, WINDUP-984 - Either take from index, or download and scan (Jandex?).
return Collections.EMPTY_LIST;
}
/**
* So that we get these packages caught Java class analysis.
*/
private void registerPackageInTypeInterestFactory(String pkg)
{
TypeInterestFactory.registerInterest(pkg + "_pkg", pkg.replace(".", "\\."), pkg, TypeReferenceLocation.IMPORT);
// TODO: Finish the implementation
}
}