001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 021 package org.sonar.graph; 022 023 import java.util.ArrayList; 024 import java.util.Collections; 025 import java.util.Iterator; 026 import java.util.List; 027 import java.util.Set; 028 029 import com.google.common.collect.HashMultiset; 030 import com.google.common.collect.Multiset; 031 032 public final class FeedbackCycle implements Iterable<FeedbackEdge>, Comparable<FeedbackCycle> { 033 034 private List<FeedbackEdge> orderedFeedbackEdges; 035 private int totalOccurrencesOfEdgesInCycle; 036 private final Cycle cycle; 037 038 private FeedbackCycle(Cycle cycle) { 039 orderedFeedbackEdges = new ArrayList<FeedbackEdge>(); 040 totalOccurrencesOfEdgesInCycle = 0; 041 this.cycle = cycle; 042 } 043 044 private void add(FeedbackEdge feedbackEdge) { 045 orderedFeedbackEdges.add(feedbackEdge); 046 } 047 048 public static List<FeedbackCycle> buildFeedbackCycles(Set<Cycle> cycles) { 049 Multiset<Edge> edgesBag = createBagWithAllEdgesOfCycles(cycles); 050 051 List<FeedbackCycle> feedbackCycles = new ArrayList<FeedbackCycle>(); 052 for (Cycle cycle : cycles) { 053 FeedbackCycle feedbackCycle = new FeedbackCycle(cycle); 054 int totalOccurrences = 0; 055 for (Edge edge : cycle.getEdges()) { 056 FeedbackEdge feedbackEdge = new FeedbackEdge(edge, edgesBag.count(edge)); 057 feedbackCycle.add(feedbackEdge); 058 totalOccurrences += feedbackEdge.getOccurences(); 059 } 060 feedbackCycle.setTotalOccurrencesOfEdgesInCycle(totalOccurrences); 061 Collections.sort(feedbackCycle.orderedFeedbackEdges); 062 feedbackCycles.add(feedbackCycle); 063 } 064 Collections.sort(feedbackCycles); 065 066 return feedbackCycles; 067 } 068 069 private static Multiset<Edge> createBagWithAllEdgesOfCycles(Set<Cycle> cycles) { 070 Multiset<Edge> edgesBag = HashMultiset.create(); 071 for (Cycle cycle : cycles) { 072 for (Edge edge : cycle.getEdges()) { 073 edgesBag.add(edge); 074 } 075 } 076 return edgesBag; 077 } 078 079 private void setTotalOccurrencesOfEdgesInCycle(int totalOccurrencesOfEdgesInCycle) { 080 this.totalOccurrencesOfEdgesInCycle = totalOccurrencesOfEdgesInCycle; 081 } 082 083 public int getTotalOccurrencesOfEdgesInCycle() { 084 return totalOccurrencesOfEdgesInCycle; 085 } 086 087 public Iterator<FeedbackEdge> iterator() { 088 return orderedFeedbackEdges.iterator(); 089 } 090 091 public int compareTo(FeedbackCycle feedbackCycle) { 092 if (getTotalOccurrencesOfEdgesInCycle() < feedbackCycle.getTotalOccurrencesOfEdgesInCycle()) { 093 return -1; 094 } 095 if (getTotalOccurrencesOfEdgesInCycle() == feedbackCycle.getTotalOccurrencesOfEdgesInCycle()) { 096 if (cycle.size() == feedbackCycle.cycle.size()) { 097 return orderedFeedbackEdges.get(0).compareTo(feedbackCycle.orderedFeedbackEdges.get(0)); 098 } 099 return cycle.size() - feedbackCycle.cycle.size(); 100 } 101 return 1; 102 } 103 104 public Cycle getCycle() { 105 return cycle; 106 } 107 }