package org.projectusus.core.filerelations.model; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; import java.util.Set; import org.jgrapht.alg.StrongConnectivityInspector; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.google.common.primitives.Ints; public class PackageRelations extends Relations<Packagename> { private PackageCycles packageCycles; private int maxLinkCount = -1; public PackageRelations() { calcPackageRelations( Predicates.<Packagename> alwaysTrue() ); calcPackageCycles(); } public PackageRelations( Predicate<Packagename> isVisible ) { calcPackageRelations( isVisible ); calcPackageCycles(); } public void calcPackageRelations( Predicate<Packagename> isVisible ) { for( ClassDescriptor source : ClassDescriptor.getAll() ) { for( ClassDescriptor target : source.getChildrenInOtherPackages() ) { if( isVisible.apply( source.getPackagename() ) && isVisible.apply( target.getPackagename() ) ) { this.add( source.getPackagename(), target.getPackagename() ); } } } } private void calcPackageCycles() { RelationGraph<Packagename> graph = new RelationGraph<Packagename>( this ); StrongConnectivityInspector<Packagename, Relation<Packagename>> inspector = new StrongConnectivityInspector<Packagename, Relation<Packagename>>( graph ); packageCycles = new PackageCycles( inspector.stronglyConnectedSets() ); } public Set<Packagename> getDirectPackageRelationsFrom( Packagename packagename ) { Set<Packagename> descriptors = new HashSet<Packagename>(); for( Relation<Packagename> relation : this.getDirectRelationsFrom( packagename ) ) { descriptors.add( relation.getTarget() ); } return descriptors; } public Set<Packagename> getDirectPackageRelationsTo( Packagename packagename ) { Set<Packagename> descriptors = new HashSet<Packagename>(); for( Relation<Packagename> relation : this.getDirectRelationsTo( packagename ) ) { descriptors.add( relation.getSource() ); } return descriptors; } public PackageCycles getPackageCycles() { return packageCycles; } public int getCrossLinkCount( Packagename source, Packagename target ) { int crossLinkCount = 0; Collection<Relation<Packagename>> relationsFromSource = getAllOutgoingRelationsFrom( source ); for( Relation<Packagename> relation : relationsFromSource ) { if( relation.getTarget().equals( target ) ) { crossLinkCount++; } } return crossLinkCount; } public int getMaxCrossLinkCount() { if( maxCrossLinkCountCached() ) { return maxLinkCount; } for( Packagename sourcePackage : outgoingRelations.keys() ) { maxLinkCount = Math.max( maxLinkCount, calculateMaxLinkCountForPackage( sourcePackage ) ); } return maxLinkCount; } private boolean maxCrossLinkCountCached() { return maxLinkCount > -1; } private int calculateMaxLinkCountForPackage( Packagename sourcePackage ) { Multimap<Packagename, Relation<Packagename>> groupedLinks = Multimaps.index( outgoingRelations.get( sourcePackage ), Relation.<Packagename> target() ); Packagename mostTargetedPackage = findMostTargetedPackage( groupedLinks ); int maxNumberOfRelations = groupedLinks.get( mostTargetedPackage ).size(); return maxNumberOfRelations; } private Packagename findMostTargetedPackage( Multimap<Packagename, Relation<Packagename>> linksByPackage ) { List<Entry<Packagename, Relation<Packagename>>> entries = new ArrayList<Entry<Packagename, Relation<Packagename>>>( linksByPackage.entries() ); Packagename mostTargetedPackage = Collections.max( entries, mapValuesComparator( linksByPackage ) ).getKey(); return mostTargetedPackage; } private Comparator<Entry<Packagename, Relation<Packagename>>> mapValuesComparator( final Multimap<Packagename, Relation<Packagename>> linksByPackage ) { return new Comparator<Entry<Packagename, Relation<Packagename>>>() { public int compare( Entry<Packagename, Relation<Packagename>> e1, Entry<Packagename, Relation<Packagename>> e2 ) { Collection<Relation<Packagename>> relationsToPackage1 = linksByPackage.get( e1.getKey() ); Collection<Relation<Packagename>> relationsToPackage2 = linksByPackage.get( e2.getKey() ); return Ints.compare( relationsToPackage1.size(), relationsToPackage2.size() ); } }; } }