package org.projectusus.ui.dependencygraph.filters;
import static com.google.common.collect.Collections2.transform;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Set;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.zest.core.viewers.EntityConnectionData;
import org.projectusus.core.filerelations.model.Packagename;
import org.projectusus.ui.dependencygraph.nodes.ClassRepresenter;
import org.projectusus.ui.dependencygraph.nodes.GraphNode;
import org.projectusus.ui.dependencygraph.nodes.PackageRepresenter;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
public class PackagenameNodeFilter extends NodeAndEdgeFilter {
private static final Joiner commaJoiner = Joiner.on( ", " );
private static final Function<EntityConnectionData, String> toArrowSeparatedStrings = new Function<EntityConnectionData, String>() {
public String apply( EntityConnectionData edge ) {
return ((PackageRepresenter)edge.source).getPackagename() + " \u2192 " + ((PackageRepresenter)edge.dest).getPackagename();
}
};
private Collection<Packagename> packages;
private Collection<EntityConnectionData> edges;
private IRestrictNodesFilterProvider filterLimitProvider;
public void setPackages( Collection<Packagename> packages ) {
this.packages = packages;
}
public void setEdges( Collection<EntityConnectionData> collectedEdges ) {
edges = collectedEdges;
}
public void resetPackages() {
setPackages( null );
setEdges( null );
}
public static PackagenameNodeFilter from( ISelection selection ) {
if( selection instanceof IStructuredSelection ) {
return from( (IStructuredSelection)selection );
}
return new PackagenameNodeFilter();
}
public static PackagenameNodeFilter from( IStructuredSelection selection ) {
PackagenameNodeFilter filter = new PackagenameNodeFilter();
filter.setPackages( collectPackages( selection ) );
filter.setEdges( collectEdges( selection ) );
return filter;
}
private static Collection<EntityConnectionData> collectEdges( IStructuredSelection selection ) {
final Collection<EntityConnectionData> edges = new LinkedList<EntityConnectionData>();
for( Object item : selection.toList() ) {
addEdge( edges, item );
}
return edges;
}
private static void addEdge( Collection<EntityConnectionData> edges, Object item ) {
if( item instanceof EntityConnectionData ) {
edges.add( (EntityConnectionData)item );
}
}
private static Collection<Packagename> collectPackages( IStructuredSelection selection ) {
final Collection<Packagename> packages = new LinkedList<Packagename>();
for( Object item : selection.toList() ) {
add( packages, item );
}
return packages;
}
private static void add( final Collection<Packagename> packages, Object item ) {
if( item instanceof PackageRepresenter ) {
add( packages, (PackageRepresenter)item );
} else if( item instanceof IPackageFragment ) {
add( packages, (IPackageFragment)item );
}
}
private static void add( final Collection<Packagename> packages, IPackageFragment fragment ) {
packages.add( Packagename.of( fragment.getElementName(), fragment ) );
}
private static void add( final Collection<Packagename> packages, PackageRepresenter representer ) {
packages.add( representer.getPackagename() );
}
public boolean isEmpty() {
return packagesAreEmpty() && edgesAreEmpty();
}
public boolean packagesAreEmpty() {
return nullOrEmpty( packages );
}
public boolean edgesAreEmpty() {
return nullOrEmpty( edges );
}
public boolean nullOrEmpty( Collection<?> collection ) {
return collection == null || collection.isEmpty();
}
@Override
protected boolean select( GraphNode node, Set<GraphNode> others ) {
return isDirectlySelected( node ) && checkRelations( node, others );
}
private boolean isDirectlySelected( GraphNode node ) {
return selectedByPackages( node ) || selectedByEdges( node );
}
private boolean checkRelations( GraphNode node, Set<GraphNode> others ) {
if( node instanceof ClassRepresenter ) {
if( !this.filterLimitProvider.isRestricting() ) {
return true;
}
ClassRepresenter representer = (ClassRepresenter)node;
for( GraphNode graphNode : others ) {
ClassRepresenter otherRepresenter = (ClassRepresenter)graphNode;
if( representer.hasConnectionTo( otherRepresenter ) && isDirectlySelected( graphNode ) ) {
return true;
}
}
return false;
}
return true;
}
private boolean selectedByEdges( GraphNode node ) {
return edges == null || isPartOfEdges( node );
}
private boolean selectedByPackages( GraphNode node ) {
return packages == null || node.isPackageOneOf( packages );
}
private boolean isPartOfEdges( GraphNode node ) {
for( EntityConnectionData edge : edges ) {
Packagename source = ((PackageRepresenter)edge.source).getPackagename();
Packagename target = ((PackageRepresenter)edge.dest).getPackagename();
if( node.isAtEitherEndOf( source, target ) ) {
return true;
}
}
return false;
}
@Override
public String getDescription() {
Collection<String> parts = new LinkedList<String>();
describeEdgesTo( parts );
describePackagesTo( parts );
return Joiner.on( '\n' ).join( parts );
}
private void describeEdgesTo( Collection<String> parts ) {
if( edgesAreEmpty() ) {
return;
}
parts.add( "Only items that cause one of the following package references: " + commaJoiner.join( transform( edges, toArrowSeparatedStrings ) ) );
}
private void describePackagesTo( Collection<String> parts ) {
if( packagesAreEmpty() ) {
return;
}
parts.add( "Only items in one of the following packages: " + commaJoiner.join( packages ) );
}
@Override
public void setFilterLimitProvider( IRestrictNodesFilterProvider filterLimitProvider ) {
this.filterLimitProvider = filterLimitProvider;
}
}