package org.jboss.windup.reporting.rules.generation;
import java.util.logging.Logger;
import javax.inject.Inject;
import org.jboss.forge.furnace.services.Imported;
import org.jboss.windup.config.AbstractRuleProvider;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.config.loader.RuleLoaderContext;
import org.jboss.windup.config.metadata.RuleMetadata;
import org.jboss.windup.config.operation.GraphOperation;
import org.jboss.windup.config.phase.PostReportGenerationPhase;
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.model.resource.SourceFileModel;
import org.jboss.windup.graph.service.GraphService;
import org.jboss.windup.graph.service.WindupConfigurationService;
import org.jboss.windup.graph.traversal.ProjectModelTraversal;
import org.jboss.windup.reporting.SourceTypeResolver;
import org.jboss.windup.reporting.model.ApplicationReportModel;
import org.jboss.windup.reporting.model.FreeMarkerSourceReportModel;
import org.jboss.windup.reporting.model.ReportFileModel;
import org.jboss.windup.reporting.model.TemplateType;
import org.jboss.windup.reporting.model.source.SourceReportModel;
import org.jboss.windup.reporting.model.source.SourceReportToProjectEdgeModel;
import org.jboss.windup.reporting.service.ApplicationReportService;
import org.jboss.windup.reporting.service.ReportService;
import org.jboss.windup.reporting.service.SourceReportService;
import org.jboss.windup.util.Logging;
import org.ocpsoft.rewrite.config.Configuration;
import org.ocpsoft.rewrite.config.ConfigurationBuilder;
import org.ocpsoft.rewrite.context.EvaluationContext;
/**
* This creates SourceReportModel entries for every relevant item within the graph.
*
* Relevancy is based on whether the item has classifications or blacklists attached to it.
*
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
*
*/
@RuleMetadata(phase = PostReportGenerationPhase.class)
public class CreateSourceReportRuleProvider extends AbstractRuleProvider
{
private static final Logger LOG = Logging.get(CreateSourceReportRuleProvider.class);
private static final String TEMPLATE = "/reports/templates/source.ftl";
@Inject
private Imported<SourceTypeResolver> resolvers;
// @formatter:off
@Override
public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext)
{
GraphOperation addSourceReports = new GraphOperation()
{
@Override
public void perform(GraphRewrite event, EvaluationContext context)
{
WindupConfigurationModel configurationModel = WindupConfigurationService.getConfigurationModel(event.getGraphContext());
Iterable<FileModel> inputApplications = configurationModel.getInputPaths();
for (FileModel inputApplication : inputApplications)
{
ProjectModelTraversal projectModelTraversal = new ProjectModelTraversal(inputApplication.getProjectModel());
traverse(event, projectModelTraversal);
}
}
@Override
public String toString()
{
return "AddSourceReport";
}
};
return ConfigurationBuilder.begin()
.addRule()
.perform(addSourceReports);
}
// @formatter:on
private void traverse(GraphRewrite event, ProjectModelTraversal traversal)
{
for (FileModel fileModel : traversal.getCanonicalProject().getFileModels())
{
if (fileModel instanceof SourceFileModel && ((SourceFileModel) fileModel).isGenerateSourceReport())
createSourceReport(event, traversal, fileModel);
}
for (ProjectModelTraversal child : traversal.getChildren())
{
traverse(event, child);
}
}
private void createSourceReport(GraphRewrite event, ProjectModelTraversal traversal, FileModel sourceFile)
{
ProjectModel application = traversal.getCurrent().getRootProjectModel();
SourceReportService sourceReportService = new SourceReportService(
event.getGraphContext());
SourceReportModel sourceReportModel = sourceReportService.getSourceReportForFileModel(sourceFile);
if (sourceReportModel != null)
{
for (SourceReportToProjectEdgeModel existing : sourceReportModel.getProjectEdges())
{
if (existing.getProjectModel().equals(application))
return;
}
// just add another project to this report
SourceReportToProjectEdgeModel toProjectEdge = sourceReportModel.addProjectModel(application);
toProjectEdge.setFullPath(traversal.getFilePath(sourceFile));
return;
}
sourceReportModel = sourceReportService.create();
ReportFileModel reportFileModel = GraphService.addTypeToModel(event.getGraphContext(), sourceFile,
ReportFileModel.class);
sourceReportModel.setSourceFileModel(reportFileModel);
SourceReportToProjectEdgeModel toProjectEdge = sourceReportModel.addProjectModel(application);
toProjectEdge.setFullPath(traversal.getFilePath(sourceFile));
sourceReportModel.setReportName(sourceFile.getPrettyPath());
sourceReportModel.setSourceType(resolveSourceType(sourceFile));
sourceReportModel.setReportName(sourceFile.getFileName());
sourceReportModel.setTemplatePath(TEMPLATE);
sourceReportModel.setTemplateType(TemplateType.FREEMARKER);
ApplicationReportService applicationReportService = new ApplicationReportService(event.getGraphContext());
ApplicationReportModel mainAppReport = applicationReportService.getMainApplicationReportForFile(sourceFile);
if (mainAppReport != null)
{
sourceReportModel.setParentReport(mainAppReport);
}
GraphService.addTypeToModel(event.getGraphContext(), sourceReportModel, FreeMarkerSourceReportModel.class);
ReportService reportService = new ReportService(event.getGraphContext());
reportService.setUniqueFilename(sourceReportModel, sourceFile.getFileName(), "html");
}
private String resolveSourceType(FileModel f)
{
for (SourceTypeResolver resolver : resolvers)
{
String resolvedType = resolver.resolveSourceType(f);
if (resolvedType != null)
{
return resolvedType;
}
}
return "unknown";
}
}