package org.jboss.windup.reporting.service; import java.util.Collections; import java.util.Map; import org.apache.commons.collections.map.LRUMap; import org.jboss.windup.config.AbstractRuleLifecycleListener; import org.jboss.windup.config.GraphRewrite; import org.jboss.windup.config.RuleLifecycleListener; import org.jboss.windup.config.Variables; import org.jboss.windup.graph.model.resource.FileModel; import org.jboss.windup.reporting.model.ClassificationModel; import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.gremlin.java.GremlinPipeline; /** * @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a> */ class ClassificationServiceCache extends AbstractRuleLifecycleListener implements RuleLifecycleListener { /** * Keep a cache of items files associated with classification in order to improve performance. */ @SuppressWarnings("unchecked") private static synchronized Map<String, Boolean> getCache(GraphRewrite event) { Map<String, Boolean> result = (Map<String, Boolean>)event.getRewriteContext().get(ClassificationServiceCache.class); if (result == null) { result = Collections.synchronizedMap(new LRUMap(30000)); event.getRewriteContext().put(ClassificationServiceCache.class, result); } return result; } /** * Indicates whether or not the given {@link FileModel} is already attached to the {@link ClassificationModel}. * * Note that this assumes all {@link ClassificationModel} attachments are handled via the {@link ClassificationService}. * * Outside of tests, this should be a safe assumption to make. */ static boolean isClassificationLinkedToFileModel(GraphRewrite event, ClassificationModel classificationModel, FileModel fileModel) { String key = getClassificationFileModelCacheKey(classificationModel, fileModel); Boolean linked = getCache(event).get(key); if (linked == null) { GremlinPipeline<Vertex, Vertex> existenceCheck = new GremlinPipeline<>(classificationModel.asVertex()); existenceCheck.out(ClassificationModel.FILE_MODEL); existenceCheck.retain(Collections.singleton(fileModel.asVertex())); linked = existenceCheck.iterator().hasNext(); cacheClassificationFileModel(event, classificationModel, fileModel, linked); } return linked; } /** * Cache the status of the link between the provided {@link ClassificationModel} and the given {@link FileModel}. */ static void cacheClassificationFileModel(GraphRewrite event, ClassificationModel classificationModel, FileModel fileModel, boolean linked) { String key = getClassificationFileModelCacheKey(classificationModel, fileModel); getCache(event).put(key, linked); } private static String getClassificationFileModelCacheKey(ClassificationModel classificationModel, FileModel fileModel) { StringBuilder builder = new StringBuilder(); if (classificationModel != null) builder.append(classificationModel.asVertex().getId()); builder.append("_"); if (fileModel != null) builder.append(fileModel.asVertex().getId()); return builder.toString(); } @Override public void beforeExecution(GraphRewrite event) { getCache(event).clear(); } @Override public void afterExecution(GraphRewrite event) { getCache(event).clear(); } }