package br.uff.ic.dyevc.graph; //~--- non-JDK imports -------------------------------------------------------- import br.uff.ic.dyevc.application.IConstants; import br.uff.ic.dyevc.exception.DyeVCException; import br.uff.ic.dyevc.exception.VCSException; import br.uff.ic.dyevc.gui.core.MessageManager; import br.uff.ic.dyevc.model.CommitInfo; import br.uff.ic.dyevc.model.CommitRelationship; import br.uff.ic.dyevc.model.topology.CloneRelationship; import br.uff.ic.dyevc.model.topology.CommitFilter; import br.uff.ic.dyevc.model.topology.CommitReturnFieldsFilter; import br.uff.ic.dyevc.model.topology.RepositoryInfo; import br.uff.ic.dyevc.model.topology.Topology; import br.uff.ic.dyevc.persistence.CommitDAO; import br.uff.ic.dyevc.persistence.TopologyDAO; import br.uff.ic.dyevc.tools.vcs.git.GitCommitTools; import br.uff.ic.dyevc.utils.DiffBetweenReps; import br.uff.ic.dyevc.utils.TrackedCommitPredicate; import edu.uci.ics.jung.graph.DirectedOrderedSparseMultigraph; import edu.uci.ics.jung.graph.DirectedSparseMultigraph; import edu.uci.ics.jung.graph.util.EdgeType; import org.apache.commons.collections15.CollectionUtils; import org.apache.commons.collections15.Predicate; import org.slf4j.LoggerFactory; //~--- JDK imports ------------------------------------------------------------ import java.util.Collection; import java.util.Map; import java.util.Set; /** * A basic repository history graph implemented as a DAG that relates all the commits with its parents and children * * @author Cristiano */ public class GraphBuilder { static Set<CommitInfo> notInPushList; static Set<CommitInfo> notInPullList; static Set<CommitInfo> notInRepList; /** * Creates a dag representing the commit history for the specified repository * * @param tools An instance of GitCommitTools to get commits history. * @return a graph representing the repository * @throws VCSException */ public static DirectedOrderedSparseMultigraph<CommitInfo, CommitRelationship> createBasicRepositoryHistoryGraph(GitCommitTools tools) throws VCSException { LoggerFactory.getLogger(GraphBuilder.class).trace("createBasicRepositoryHistoryGraph -> Entry"); final DirectedOrderedSparseMultigraph<CommitInfo, CommitRelationship> graph = new DirectedOrderedSparseMultigraph<CommitInfo, CommitRelationship>(); notInPushList = tools.getCommitsNotInPushList(); notInPullList = tools.getCommitsNotInPullList(); notInRepList = tools.getCommitsNotFoundLocally(); try { for (CommitInfo commitInfo : tools.getCommitInfos()) { adjustCommitType(commitInfo); graph.addVertex(commitInfo); } for (CommitRelationship commitRelationship : tools.getCommitRelationships()) { graph.addEdge(commitRelationship, commitRelationship.getChild(), commitRelationship.getParent()); } } catch (VCSException ex) { MessageManager.getInstance().addMessage("Error during graph creation: " + ex); throw ex; } LoggerFactory.getLogger(GraphBuilder.class).trace("createBasicRepositoryHistoryGraph -> Exit"); return graph; } /** * Creates a dag representing the topology of a given system * * @param systemName the name of the system for which the graph will be created * @return a graph representing the topology * @throws DyeVCException */ public static DirectedSparseMultigraph<RepositoryInfo, CloneRelationship> createTopologyGraph(String systemName) throws DyeVCException { LoggerFactory.getLogger(GraphBuilder.class).trace("createTopologyGraph -> Entry"); final DirectedSparseMultigraph<RepositoryInfo, CloneRelationship> graph = new DirectedSparseMultigraph<RepositoryInfo, CloneRelationship>(); try { TopologyDAO dao = new TopologyDAO(); Topology top = dao.readTopologyForSystem(systemName); CommitFilter filter = new CommitFilter(); filter.setSystemName(systemName); CommitReturnFieldsFilter returnFields = new CommitReturnFieldsFilter(); returnFields.setTracked("1"); returnFields.setFoundIn("1"); Set<CommitInfo> allSystemCommits = new CommitDAO().getCommitsByQuery(filter, returnFields); for (RepositoryInfo cloneInfo : top.getClonesForSystem(systemName)) { graph.addVertex(cloneInfo); LoggerFactory.getLogger(GraphBuilder.class).debug("Vertex added: " + cloneInfo); } DiffBetweenReps diff = new DiffBetweenReps(); TrackedCommitPredicate commitPredicate = new TrackedCommitPredicate(); for (CloneRelationship cloneRelationship : top.getRelationshipsForSystem(systemName)) { diff.setOriginId(cloneRelationship.getOrigin().getId()); diff.setDestinationId(cloneRelationship.getDestination().getId()); Collection<CommitInfo> diffCommits = CollectionUtils.select(allSystemCommits, diff); int tracked = CollectionUtils.select(diffCommits, commitPredicate).size(); cloneRelationship.setNonSyncTrackedCommitsCount(tracked); int nonTracked = diffCommits.size() - tracked; cloneRelationship.setNonSyncNonTrackedCommitsCount(nonTracked); graph.addEdge(cloneRelationship, cloneRelationship.getOrigin(), cloneRelationship.getDestination(), EdgeType.DIRECTED); LoggerFactory.getLogger(GraphBuilder.class).debug("Edge added: " + cloneRelationship); } } catch (DyeVCException ex) { MessageManager.getInstance().addMessage("Error during graph creation: " + ex); throw ex; } LoggerFactory.getLogger(GraphBuilder.class).trace("createTopologyGraph -> Exit"); return graph; } private static void adjustCommitType(CommitInfo ci) { boolean allHave = !(notInRepList.contains(ci)) || notInPushList.contains(ci); boolean iHavePushDoesnt = !notInRepList.contains(ci) && notInPushList.contains(ci); boolean iDontHaveSomePullHas = notInRepList.contains(ci) &&!notInPullList.contains(ci); boolean noOneKnownHas = notInRepList.contains(ci) && notInPushList.contains(ci) && notInPullList.contains(ci); if (!ci.isTracked()) { ci.setType(IConstants.COMMIT_MASK_NOT_TRACKED); return; } if (allHave) { ci.setType(IConstants.COMMIT_MASK_ALL_HAVE); } if (iHavePushDoesnt) { ci.setType(IConstants.COMMIT_MASK_I_HAVE_PUSH_DONT); } if (iDontHaveSomePullHas) { ci.setType(IConstants.COMMIT_MASK_I_DONT_PULL_HAS); } if (noOneKnownHas) { ci.setType(IConstants.COMMIT_MASK_NON_RELATED_HAS); } } }