OSDN Git Service

a3fd83e601719cb24882c0b904268663491ff375
[stigmata/stigmata.git] / src / main / java / jp / sourceforge / stigmata / ui / swing / RoundRobinComparisonResultPane.java
1 package jp.sourceforge.stigmata.ui.swing;
2
3 /*
4  * $Id$
5  */
6
7 import java.awt.BorderLayout;
8 import java.awt.Component;
9 import java.awt.GridLayout;
10 import java.awt.event.ActionEvent;
11 import java.awt.event.ActionListener;
12 import java.awt.event.MouseAdapter;
13 import java.awt.event.MouseEvent;
14 import java.io.File;
15 import java.io.IOException;
16 import java.io.PrintWriter;
17 import java.net.URL;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.Map;
21
22 import javax.swing.Box;
23 import javax.swing.JButton;
24 import javax.swing.JComponent;
25 import javax.swing.JLabel;
26 import javax.swing.JMenuItem;
27 import javax.swing.JOptionPane;
28 import javax.swing.JPanel;
29 import javax.swing.JScrollPane;
30 import javax.swing.JTable;
31 import javax.swing.border.TitledBorder;
32 import javax.swing.table.DefaultTableModel;
33
34 import jp.sourceforge.stigmata.Birthmark;
35 import jp.sourceforge.stigmata.BirthmarkComparator;
36 import jp.sourceforge.stigmata.BirthmarkContext;
37 import jp.sourceforge.stigmata.BirthmarkEnvironment;
38 import jp.sourceforge.stigmata.BirthmarkSet;
39 import jp.sourceforge.stigmata.BirthmarkStoreException;
40 import jp.sourceforge.stigmata.ComparisonResultSet;
41 import jp.sourceforge.stigmata.ExtractionResultSet;
42 import jp.sourceforge.stigmata.ExtractionTarget;
43 import jp.sourceforge.stigmata.filter.FilteredComparisonResultSet;
44 import jp.sourceforge.stigmata.printer.PrinterManager;
45 import jp.sourceforge.stigmata.result.CertainPairComparisonResultSet;
46 import jp.sourceforge.stigmata.result.RoundRobinComparisonResultSet;
47 import jp.sourceforge.stigmata.spi.ResultPrinterSpi;
48 import jp.sourceforge.stigmata.ui.swing.actions.SaveAction;
49 import jp.sourceforge.stigmata.ui.swing.actions.UpdateBirthmarkCellColorAction;
50 import jp.sourceforge.stigmata.utils.AsciiDataWritable;
51 import jp.sourceforge.talisman.i18n.Messages;
52
53 /**
54  * 
55  * @author Haruaki TAMADA
56  * @version $Revision$ 
57  */
58 public class RoundRobinComparisonResultPane extends JPanel{
59     private static final long serialVersionUID = 2134574576543623L;
60
61     private StigmataFrame stigmata;
62     private ExtractionResultSet extraction;
63     private JTable table;
64     private DefaultTableModel model;
65     private JLabel classCount, comparisonCount, distinctionRatio;
66     private JLabel average, minimum, maximum;
67
68     public RoundRobinComparisonResultPane(StigmataFrame stigmata, ExtractionResultSet resultset){
69         this.stigmata = stigmata;
70         this.extraction = resultset;
71         initialize();
72         compare(model);
73     }
74
75     private void compare(DefaultTableModel model){
76         ExtractionTarget targetX = ExtractionTarget.TARGET_X;
77         ExtractionTarget targetY = ExtractionTarget.TARGET_Y;
78         int countX = extraction.getBirthmarkSetSize(targetX);
79         int countY = extraction.getBirthmarkSetSize(targetY);
80         int comparisonCount = countX * countY;
81         if(countX == 0 && countY == 0){
82             targetX = ExtractionTarget.TARGET_XY;
83             targetY = ExtractionTarget.TARGET_XY;
84             countX = extraction.getBirthmarkSetSize(targetX);
85             countY = extraction.getBirthmarkSetSize(targetY);
86             comparisonCount = countX * (countY - 1) / 2;
87         }
88         else if(countX == 0 || countY == 0){
89             targetX = ExtractionTarget.TARGET_BOTH;
90             targetY = ExtractionTarget.TARGET_BOTH;
91             countX = extraction.getBirthmarkSetSize(targetX);
92             countY = extraction.getBirthmarkSetSize(targetY);
93             comparisonCount = countX * (countY - 1) / 2;
94         }
95
96         classCount.setText(Integer.toString(countX + countY));
97         this.comparisonCount.setText(Integer.toString(comparisonCount));
98         int correct = 0;
99         double avg = 0d;
100         double max = 0d;
101         double min = 100d;
102         model.addColumn("");
103         for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(targetX); i.hasNext(); ){
104             BirthmarkSet x = i.next();
105             model.addColumn(x.getName());
106         }
107         int sizeX = extraction.getBirthmarkSetSize(targetX);
108         for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(targetY); i.hasNext(); ){
109             Object[] rows = new Object[sizeX + 1];
110             BirthmarkSet setY = i.next();
111             rows[0] = setY.getName();
112
113             int index = 0;
114             for(Iterator<BirthmarkSet> j = extraction.birthmarkSets(targetX); j.hasNext(); ){
115                 BirthmarkSet setX = j.next();
116                 double similarity = compare(setX, setY, extraction.getContext());
117                 rows[index + 1] = new Double(similarity);
118
119                 if(Math.abs(similarity - 1) < 1E-8){
120                     correct += 1;
121                 }
122                 avg += similarity;
123                 if(max < similarity) max = similarity;
124                 if(min > similarity) min = similarity;
125                 index++;
126             }
127             model.addRow(rows);
128         }
129         distinctionRatio.setText(
130             Double.toString((double)(comparisonCount - correct) / (double)comparisonCount)
131         );
132         avg = avg / comparisonCount;
133         average.setText(Double.toString(avg));
134         minimum.setText(Double.toString(min));
135         maximum.setText(Double.toString(max));
136     }
137
138     private double compare(BirthmarkSet x, BirthmarkSet y, BirthmarkContext context){
139         double similarity = 0d;
140         int count = 0;
141
142         for(String type: x.getBirthmarkTypes()){
143             Birthmark b1 = x.getBirthmark(type);
144             Birthmark b2 = y.getBirthmark(type);
145             if(b1 != null && b2 != null){
146                 BirthmarkComparator comparator = context.getEnvironment().getService(type).getComparator();
147                 double result = comparator.compare(b1, b2, context);
148                 if(!Double.isNaN(result)){
149                     similarity += result;
150                     count++;
151                 }
152             }
153         }
154         return similarity / count;
155     }
156
157     private Component getMainPane(){
158         JPanel panel = new JPanel();
159         panel.setLayout(new BorderLayout());
160
161         model = new RoundRobinComparisonResultSetTableModel();
162         table = new JTable(model);
163         table.setDefaultRenderer(Double.class, new CompareTableCellRenderer(extraction.getEnvironment()));
164         table.addMouseListener(new MouseAdapter(){
165             @Override
166             public void mouseClicked(MouseEvent e){
167                 if(e.getClickCount() == 2){
168                     int row = table.rowAtPoint(e.getPoint());
169                     int col = table.columnAtPoint(e.getPoint());
170                     if(col >= 1 && col < table.getColumnCount() && row >= 0
171                             && row < table.getRowCount()){
172                         BirthmarkSet b1 = extraction.getBirthmarkSet(ExtractionTarget.TARGET_X, col - 1);
173                         BirthmarkSet b2 = extraction.getBirthmarkSet(ExtractionTarget.TARGET_Y, row);
174
175                         stigmata.compareDetails(b1, b2, extraction.getContext());
176                     }
177                 }
178             }
179         });
180         table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
181         table.setCellSelectionEnabled(true);
182         JScrollPane scroll = new JScrollPane();
183         scroll.setViewportView(table);
184         scroll.setWheelScrollingEnabled(true);
185         panel.add(scroll, BorderLayout.CENTER);
186         JComponent south = Box.createVerticalBox();
187         JPanel box1 = new JPanel(new GridLayout(1, 3));
188         box1.add(classCount = new JLabel());
189         box1.add(comparisonCount = new JLabel());
190         box1.add(distinctionRatio = new JLabel());
191         south.add(box1);
192         JPanel box2 = new JPanel(new GridLayout(1, 3));
193         box2.setBorder(new TitledBorder(stigmata.getMessages().get("similarity.border")));
194         box2.add(average = new JLabel());
195         box2.add(minimum = new JLabel());
196         box2.add(maximum = new JLabel());
197         south.add(box2);
198
199         classCount.setBorder(new TitledBorder(stigmata.getMessages().get("numberofclasses.border")));
200         comparisonCount.setBorder(new TitledBorder(stigmata.getMessages().get("comparisoncount.border")));
201         distinctionRatio.setBorder(new TitledBorder(stigmata.getMessages().get("distinctionratio.border")));
202         average.setBorder(new TitledBorder(stigmata.getMessages().get("average.border")));
203         minimum.setBorder(new TitledBorder(stigmata.getMessages().get("minimum.border")));
204         maximum.setBorder(new TitledBorder(stigmata.getMessages().get("maximum.border")));
205
206         panel.add(south, BorderLayout.SOUTH);
207
208         return panel;
209     }
210
211     private void mdsButtonActionPerformed(ActionEvent e){
212         Map<URL, BirthmarkSet> map = new HashMap<URL, BirthmarkSet>();
213         for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(ExtractionTarget.TARGET_X); i.hasNext(); ){
214             BirthmarkSet bs = i.next();
215             map.put(bs.getLocation(), bs);
216         }
217         for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(ExtractionTarget.TARGET_Y); i.hasNext(); ){
218             BirthmarkSet bs = i.next();
219             map.put(bs.getLocation(), bs);
220         }
221         int index = 0;
222         BirthmarkSet[] set = new BirthmarkSet[map.size()];
223         for(Map.Entry<URL, BirthmarkSet> entry: map.entrySet()){
224             set[index] = entry.getValue();
225             index++;
226         }
227         
228         stigmata.showMdsGraph(set, extraction.getContext());
229     }
230
231     private void graphButtonActionPerformed(ActionEvent e){
232         Map<Integer, Integer> values = new HashMap<Integer, Integer>();
233         for(int i = 0; i < table.getRowCount(); i++){
234             for(int j = 1; j < table.getColumnCount(); j++){
235                 Double d = (Double)table.getValueAt(i, j);
236                 int similarity = (int)Math.round(d.doubleValue() * 100);
237                 Integer dist = values.get(new Integer(similarity));
238                 if(dist == null){
239                     dist = new Integer(0);
240                 }
241                 dist = new Integer(dist.intValue() + 1);
242                 values.put(new Integer(similarity), dist);
243             }
244         }
245         stigmata.showSimilarityDistributionGraph(values);
246     }
247
248     private void initialize(){
249         final Messages messages = stigmata.getMessages();
250         JButton save = GUIUtility.createButton(
251             messages, "savecomparison", new SaveAction(stigmata, new AsciiDataWritable(){
252                 @Override
253                 public void writeAsciiData(PrintWriter out, String format){
254                     ResultPrinterSpi service = PrinterManager.getInstance().getService(format);
255                     if(service == null){
256                         service = PrinterManager.getDefaultFormatService();
257                     }
258
259                     service.getComparisonResultSetPrinter().printResult(
260                         out, new RoundRobinComparisonResultSet(extraction)
261                     );
262                 }
263             }
264         ));
265         JButton graph = GUIUtility.createButton(messages, "showgraph");
266         JButton obfuscate = GUIUtility.createButton(messages, "obfuscate");
267         JButton compare = GUIUtility.createButton(messages, "guessedpair");
268         JButton updateColor = GUIUtility.createButton(
269             messages, "updatecellcolor",
270             new UpdateBirthmarkCellColorAction(stigmata, extraction.getEnvironment())
271         );
272         JMenuItem mdsMenu = GUIUtility.createJMenuItem(messages, "mdsmap");
273
274         PopupButton comparePopup = new PopupButton(compare);
275         PopupButton graphPopup = new PopupButton(graph);
276
277         JComponent southPanel = Box.createHorizontalBox();
278
279         setLayout(new BorderLayout());
280         add(getMainPane(), BorderLayout.CENTER);
281         add(southPanel, BorderLayout.SOUTH);
282         southPanel.add(Box.createHorizontalGlue());
283         southPanel.add(save);
284         southPanel.add(Box.createHorizontalGlue());
285         southPanel.add(updateColor);
286         southPanel.add(Box.createHorizontalGlue());
287         southPanel.add(graphPopup);
288         southPanel.add(Box.createHorizontalGlue());
289         southPanel.add(obfuscate);
290         southPanel.add(Box.createHorizontalGlue());
291         southPanel.add(comparePopup);
292         southPanel.add(Box.createHorizontalGlue());
293
294         graph.addActionListener(new ActionListener(){
295             @Override
296             public void actionPerformed(ActionEvent e){
297                 graphButtonActionPerformed(e);
298             }
299         });
300         mdsMenu.addActionListener(new ActionListener(){
301             @Override
302             public void actionPerformed(ActionEvent e){
303                 mdsButtonActionPerformed(e);
304             }
305         });
306
307         obfuscate.addActionListener(new ActionListener(){
308             @Override
309             public void actionPerformed(ActionEvent e){
310                 obfuscateClassNames();
311             }
312         });
313
314         ActionListener compareListener = new ActionListener(){
315             @Override
316             public void actionPerformed(ActionEvent e){
317                 String item = e.getActionCommand();
318                 if(item.equals("guessedpair")){
319                     compareGuessedPair();
320                 }
321                 else if(item.equals("specifiedpair")){
322                     compareSpecifiedPair();
323                 }
324                 else if(item.equals("roundrobin.filtering")){
325                     compareRoundRobinWithFiltering();
326                 }
327             }
328         };
329
330         compare.addActionListener(compareListener);
331         String[] comparisonMethods = stigmata.getMessages().getArray("comparison.methods.inroundrobinresult");
332         for(int i = 1; i < comparisonMethods.length; i++){
333             JMenuItem item = GUIUtility.createJMenuItem(messages, comparisonMethods[i]);
334             comparePopup.addMenuItem(item);
335             item.addActionListener(compareListener);
336         }
337         graphPopup.addMenuItem(mdsMenu);
338     }
339
340     private void compareRoundRobinWithFiltering(){
341         FilterSelectionPane pane = new FilterSelectionPane(
342             stigmata, extraction.getEnvironment().getFilterManager()
343         );
344         int returnValue = JOptionPane.showConfirmDialog(
345             stigmata, pane, stigmata.getMessages().get("filterselection.dialog.title"),
346             JOptionPane.OK_CANCEL_OPTION,
347             JOptionPane.QUESTION_MESSAGE
348         );
349         if(returnValue == JOptionPane.OK_OPTION){
350             String[] filterSetList = pane.getSelectedFilters();
351
352             ComparisonResultSet rs = new RoundRobinComparisonResultSet(extraction);
353             
354             ComparisonResultSet filterResultSet = new FilteredComparisonResultSet(
355                 rs, extraction.getEnvironment().getFilterManager().getFilterSets(filterSetList)
356             );
357             stigmata.showComparisonResultSet(filterResultSet);
358         }
359     }
360
361     private void compareGuessedPair(){
362         ComparisonResultSet rs = new CertainPairComparisonResultSet(extraction);
363         stigmata.showComparisonResultSet(rs);
364     }
365
366     private void compareSpecifiedPair(){
367         File file = stigmata.getOpenFile(
368             stigmata.getMessages().getArray("comparemapping.extension"),
369             stigmata.getMessages().get("comparemapping.description")
370         );
371         if(file != null){
372             Map<String, String> mapping = stigmata.constructMapping(file);
373
374             ComparisonResultSet comparison = new CertainPairComparisonResultSet(extraction, mapping);
375             stigmata.showComparisonResultSet(comparison);
376         }
377     }
378
379     private void obfuscateClassNames(){
380         ClassNameObfuscator obfuscator = new ClassNameObfuscator();
381
382         try{
383             File file = stigmata.getSaveFile(
384                 stigmata.getMessages().getArray("obfuscationmapping.extension"),
385                 stigmata.getMessages().get("obfuscationmapping.description")
386             );
387             if(file != null){
388                 BirthmarkContext context = extraction.getContext();
389                 BirthmarkEnvironment env = context.getEnvironment();
390                 ExtractionResultSet ers = env.getHistoryManager().createDefaultResultSet(context);
391                 try{
392                     for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(ExtractionTarget.TARGET_X); i.hasNext(); ){
393                         BirthmarkSet bs = i.next();
394                         ers.addBirthmarkSet(ExtractionTarget.TARGET_X, obfuscator.obfuscateClassName(bs));
395                     }
396                     for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(ExtractionTarget.TARGET_Y); i.hasNext(); ){
397                         BirthmarkSet bs = i.next();
398                         ers.addBirthmarkSet(ExtractionTarget.TARGET_Y, obfuscator.obfuscateClassName(bs));
399                     }
400                 } catch(BirthmarkStoreException e){
401                 }
402                 this.extraction = ers;
403                 obfuscator.outputNameMappings(file);
404             }
405         }catch(IOException e){
406             JOptionPane.showMessageDialog(
407                 this, e.getMessage(), stigmata.getMessages().get("error.dialog.title"),
408                 JOptionPane.ERROR_MESSAGE
409             );
410             return;
411         }
412
413         DefaultTableModel model = new RoundRobinComparisonResultSetTableModel();
414         compare(model);
415         table.setModel(model);
416         this.model = model;
417     }
418
419     private static class RoundRobinComparisonResultSetTableModel extends DefaultTableModel{
420         private static final long serialVersionUID = 765435324523543242L;
421
422         @Override
423         public boolean isCellEditable(int row, int col){
424             return false;
425         }
426
427         @Override
428         public Class<?> getColumnClass(int column){
429             if(column == 0){
430                 return String.class;
431             }
432             else{
433                 return Double.class;
434             }
435         }
436     }
437 }