001    package org.expasy.jpl.commons.collection.graph;
002    
003    
004    import java.io.PrintStream;
005    import java.util.ArrayList;
006    import java.util.Collection;
007    import java.util.Collections;
008    import java.util.Comparator;
009    import java.util.List;
010    import org.apache.commons.collections15.Predicate;
011    import org.apache.commons.collections15.Transformer;
012    import org.expasy.jpl.commons.base.builder.BuilderException;
013    import org.expasy.jpl.commons.base.builder.InstanceBuilder;
014    import edu.uci.ics.jung.graph.Graph;
015    import edu.uci.ics.jung.graph.util.Pair;
016    
017    
018    /**
019     * This object exports graphs.
020     * 
021     * @author nikitin
022     * 
023     * @version 1.0
024     * 
025     */
026    public final class GraphExporter<V, E> {
027            
028            private static final ObjectComparator UNIVERSAL_COMPARATOR =
029                new ObjectComparator();
030            private Transformer<E, String> edgeValueTransformer;
031            
032            private PrintStream ps;
033            private List<Predicate<V>> predicateFilters;
034            
035            private GraphExporter(Builder<V, E> builder) {
036                    ps = builder.ps;
037                    edgeValueTransformer = builder.edgeValueTransformer;
038                    predicateFilters = builder.predicates;
039            }
040            
041            public static class Builder<V, E> implements
042                InstanceBuilder<GraphExporter<V, E>> {
043                    
044                    private PrintStream ps;
045                    private List<Predicate<V>> predicates;
046                    private Transformer<E, String> edgeValueTransformer =
047                        new Transformer<E, String>() {
048                                
049                                @Override
050                                public String transform(E edge) {
051                                        return edge.toString();
052                                }
053                                
054                        };
055                    
056                    public Builder() {
057                            ps = System.out;
058                            predicates = new ArrayList<Predicate<V>>();
059                    }
060                    
061                    public Builder<V, E> printStream(PrintStream ps) {
062                            this.ps = ps;
063                            return this;
064                    }
065                    
066                    public Builder<V, E> predicate(Predicate<V> predicate) {
067                            predicates.add(predicate);
068                            return this;
069                    }
070                    
071                    public Builder<V, E> edgeValueTransformer(
072                        Transformer<E, String> transformer) {
073                            edgeValueTransformer = transformer;
074                            return this;
075                    }
076                    
077                    @Override
078                    public GraphExporter<V, E> build() throws BuilderException {
079                            return new GraphExporter<V, E>(this);
080                    }
081                    
082            }
083            
084            public static <V, E> GraphExporter<V, E> newInstance() {
085                    return new GraphExporter.Builder<V, E>().build();
086            }
087            
088            public String export(Graph<V, E> graph,
089                Transformer<Graph<V, E>, String> transformer) {
090                    
091                    return transformer.transform(graph);
092            }
093            
094            public void exportKPGraph(KPartiteGraphImpl<V, E> g) {
095                    // all predicates by default
096                    Collection<Predicate<V>> preds = g.getPartitions();
097                    
098                    ps.print("KPGraph " + g.getId() + "\n");
099                    ps.print(" |-- Vertices (x");
100                    
101                    // filter on predicates
102                    if (predicateFilters != null && predicateFilters.size() > 0) {
103                            preds = predicateFilters;
104                            ps.print(g.getVertexCount(preds));
105                    } else {
106                            ps.print(g.getVertexCount());
107                    }
108                    ps.print(")\n");
109                    
110                    int count = 0;
111                    Predicate<V> lastPredicate = null;
112                    List<V> nodes;
113                    for (Predicate<V> predicate : preds) {
114                            if (count == preds.size() - 1) {
115                                    lastPredicate = predicate;
116                                    break;
117                            }
118                            
119                            nodes = new ArrayList<V>(g.getVertices(predicate));
120                            
121                            ps.print(" |   |-- predicate-" + count);
122                            ps.print(" (x" + nodes.size() + ")\n");
123                            
124                            if (nodes.size() > 0) {
125                                    Collections.sort(nodes, UNIVERSAL_COMPARATOR);
126                                    
127                                    for (int i = 0; i < nodes.size() - 1; i++) {
128                                            ps.print(" |   |   |-- ");
129                                            ps.print(nodes.get(i));
130                                            ps.print("\n");
131                                    }
132                                    // last vertex
133                                    ps.print(" |   |   `-- ");
134                                    ps.print(nodes.get(nodes.size() - 1));
135                                    ps.print("\n");
136                            }
137                            count++;
138                    }
139                    // last predicate
140                    nodes = new ArrayList<V>(g.getVertices(lastPredicate));
141                    
142                    ps.print(" |   `-- predicate-" + count);
143                    ps.print(" (x" + nodes.size() + ")\n");
144                    
145                    if (nodes.size() > 0) {
146                            Collections.sort(nodes, UNIVERSAL_COMPARATOR);
147                            for (int i = 0; i < nodes.size() - 1; i++) {
148                                    ps.print(" |       |-- ");
149                                    ps.print(nodes.get(i));
150                                    ps.print("\n");
151                            }
152                            // last vertex
153                            ps.print(" |       `-- ");
154                            ps.print(nodes.get(nodes.size() - 1));
155                            ps.print("\n");
156                    }
157                    
158                    ps.print(" `-- Edges (x");
159                    
160                    // filter on predicates
161                    if (predicateFilters != null && predicateFilters.size() > 0) {
162                            ps.print(g.getEdgeCount(preds));
163                    } else {
164                            ps.print(g.getEdgeCount());
165                    }
166                    ps.print(")\n");
167                    
168                    count = 0;
169                    
170                    Pair<V> pair = null;
171                    E lastEdge = null;
172                    List<E> es = new ArrayList<E>();
173                    
174                    if (predicateFilters != null && predicateFilters.size() > 0) {
175                            es.addAll(g.getEdges(predicateFilters));
176                    } else {
177                            es.addAll(g.getEdges());
178                    }
179                    Collections.sort(es, UNIVERSAL_COMPARATOR);
180                    String edgeValueString = null;
181                    for (E edge : es) {
182                            pair = g.getEndpoints(edge);
183                            
184                            if (count == es.size() - 1) {
185                                    lastEdge = edge;
186                                    break;
187                            }
188                            
189                            ps.print("     |-- " + pair.getFirst() + " <--> "
190                                + pair.getSecond());
191                            
192                            edgeValueString = edgeValueTransformer.transform(edge);
193                            
194                            if (edgeValueString != null) {
195                                    ps.print(" (" + edgeValueString + ")");
196                            }
197                            ps.print("\n");
198                            
199                            count++;
200                    }
201                    // write last edge
202                    ps.print("     `-- " + pair.getFirst() + " <--> " + pair.getSecond());
203                    
204                    edgeValueString = edgeValueTransformer.transform(lastEdge);
205                    
206                    if (edgeValueString != null) {
207                            ps.print(" (" + edgeValueString + ")");
208                    }
209                    ps.print("\n");
210                    
211                    ps.close();
212            }
213            
214            /**
215             * @return a copy of the given undirected sparse graph.
216             */
217            public static class DotTransformer<V, E> implements
218                Transformer<Graph<V, E>, String> {
219                    
220                    @Override
221                    public String transform(Graph<V, E> graph) {
222                            final StringBuilder sb = new StringBuilder();
223                            
224                            sb.append("graph G {\n");
225                            for (final V vertex : graph.getVertices()) {
226                                    sb.append(vertex + ";\n");
227                            }
228                            for (final E edge : graph.getEdges()) {
229                                    sb.append(edge + ";\n");
230                            }
231                            sb.append("}\n");
232                            
233                            return sb.toString();
234                    }
235                    
236            }
237            
238            public static class ObjectComparator implements Comparator<Object> {
239                    
240                    @Override
241                    public int compare(Object o1, Object o2) {
242                            return o1.toString().compareTo(o2.toString());
243                    }
244                    
245            }
246    }