package com.spss.vis.sample; import com.spss.vis.Visualization; import com.spss.vis.VisualizationFactory; import com.spss.vis.processors.EPSProcessor; import com.spss.vis.specification.SpecificationChangeEvent; import com.spss.vis.specification.VisualizationSpecification; import com.spss.vis.specification.data.DelimitedFileSourceSpecification; import javax.imageio.ImageIO; import javax.swing.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.*; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.*; import java.util.prefs.Preferences; public class TagCloudExample extends JLabel { private final Preferences prefs = Preferences.userRoot(); private final Set stopwords = readStopList(); private final Visualization vis; private final VisualizationSpecification spec; private List words; // MAIN: Creates the Swing components, gets a file and shows the results public static void main(String[] args) throws Exception { JFrame top = new JFrame(); TagCloudExample b = new TagCloudExample(); b.chooseAndShowFile(); top.setContentPane(b); top.pack(); top.setLocationRelativeTo(null); top.setVisible(true); top.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public TagCloudExample() throws Exception { // When we click on the image, save the image and ask for a new one addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { try { saveImages(); chooseAndShowFile(); } catch (Exception ignored) { } } } ); // This reads the specifcation and sets everything up spec = new VisualizationSpecification(TagCloudExample.class.getResourceAsStream("tagCloud.xml")); vis = VisualizationFactory.getInstance().makeVisualization(spec); vis.setOutputSize(1000, 800); } // Read the stop list words private static Set readStopList() throws IOException { Set result = new HashSet(); InputStream stream = TagCloudExample.class.getResourceAsStream("stoplist.txt"); StreamTokenizer tok = new StreamTokenizer(new InputStreamReader(stream)); tok.resetSyntax(); tok.wordChars('a', 'z'); tok.whitespaceChars(0, 'a' - 1); tok.whitespaceChars('z' + 1, 9999); while (true) { if (tok.nextToken() == StreamTokenizer.TT_EOF) break; result.add(simplify(tok)); } return result; } public void buildFrequencies(File file) throws Exception { Map recordMap = new HashMap(); StreamTokenizer tok = makeTokenizer(file); for (int pos = 0; ; pos++) { int val = tok.nextToken(); if (val == StreamTokenizer.TT_EOF) break; else if (val == StreamTokenizer.TT_WORD) { String word = simplify(tok); if (word.length() < 3) continue; Record item = recordMap.get(word); if (item == null) { recordMap.put(word, new Record(word, pos)); } else item.count++; } } words = new ArrayList(recordMap.values()); Collections.sort(words); if (words.size() > 300) words = words.subList(0, 300); } public void chooseAndShowFile() throws Exception { JFileChooser chooser = new JFileChooser(prefs.get("tagCloudInput", ".")); chooser.showOpenDialog(null); File file = chooser.getSelectedFile(); if (file == null) return; prefs.put("tagCloudInput", file.getCanonicalPath()); buildFrequencies(file); File out = writeFrequenciesToCSVFile(); // Modify the spec to point to the data and then make the image ((DelimitedFileSourceSpecification) spec.getDataSpecifications()[0]).setFilePath(out.getCanonicalPath()); spec.fireSpecificationChangedEvent(new SpecificationChangeEvent(this, "data")); BufferedImage image = vis.makeImage(); setIcon(new ImageIcon(image)); } private File writeFrequenciesToCSVFile() throws IOException { File out = File.createTempFile("viz", "viz"); out.deleteOnExit(); NumberFormat f = DecimalFormat.getInstance(); f.setGroupingUsed(false); FileWriter w = new FileWriter(out); w.write("Word, Count, Location\n"); for (Record record : words) w.write(record.word + ',' + f.format(record.count) + ',' + f.format(record.start) + '\n'); w.close(); return out; } private void saveImages() throws Exception { JFileChooser chooser = new JFileChooser(prefs.get("tagCloudOutput", ".")); chooser.showSaveDialog(null); File file = chooser.getSelectedFile(); if (file != null) { prefs.put("tagCloudOutput", file.getCanonicalPath()); vis.runProcessor(new EPSProcessor(new FileOutputStream(file))); ImageIO.write((RenderedImage) ((ImageIcon) getIcon()).getImage(), "png", new File(file.getCanonicalPath() + ".png")); } } private StreamTokenizer makeTokenizer(File file) throws FileNotFoundException { Reader r = new BufferedReader(new FileReader(file), 100 * 1024); StreamTokenizer tok = new StreamTokenizer(r); tok.resetSyntax(); tok.wordChars('a', 'z'); tok.wordChars('A', 'Z'); return tok; } private static String simplify(StreamTokenizer tok) { String s = tok.sval.toLowerCase(Locale.US); if (s.length() < 3 || s.length() > 25) return ""; if (!Character.isLetter(s.charAt(0))) s = s.substring(1); if (!Character.isLetter(s.charAt(s.length() - 1))) s = s.substring(0, s.length() - 1); return s; } private class Record implements Comparable { private final int start; private final String word; private int count = 1; public Record(String word, int start) { this.word = word; this.start = start; } public int compareTo(Record other) { return other.count == count ? word.compareTo(other.word) : other.count - count; } } }