OSDN Git Service

Remove Date tag of Subversion
[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.getEnvironment());
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, BirthmarkEnvironment environment){
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 = environment.getService(type).getComparator();
147                 double result = comparator.compare(b1, b2);
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             public void mouseClicked(MouseEvent e){
166                 if(e.getClickCount() == 2){
167                     int row = table.rowAtPoint(e.getPoint());
168                     int col = table.columnAtPoint(e.getPoint());
169                     if(col >= 1 && col < table.getColumnCount() && row >= 0
170                             && row < table.getRowCount()){
171                         BirthmarkSet b1 = extraction.getBirthmarkSet(ExtractionTarget.TARGET_X, col - 1);
172                         BirthmarkSet b2 = extraction.getBirthmarkSet(ExtractionTarget.TARGET_Y, row);
173
174                         stigmata.compareDetails(b1, b2, extraction.getContext());
175                     }
176                 }
177             }
178         });
179         table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
180         table.setCellSelectionEnabled(true);
181         JScrollPane scroll = new JScrollPane();
182         scroll.setViewportView(table);
183         scroll.setWheelScrollingEnabled(true);
184         panel.add(scroll, BorderLayout.CENTER);
185         JComponent south = Box.createVerticalBox();
186         JPanel box1 = new JPanel(new GridLayout(1, 3));
187         box1.add(classCount = new JLabel());
188         box1.add(comparisonCount = new JLabel());
189         box1.add(distinctionRatio = new JLabel());
190         south.add(box1);
191         JPanel box2 = new JPanel(new GridLayout(1, 3));
192         box2.setBorder(new TitledBorder(stigmata.getMessages().get("similarity.border")));
193         box2.add(average = new JLabel());
194         box2.add(minimum = new JLabel());
195         box2.add(maximum = new JLabel());
196         south.add(box2);
197
198         classCount.setBorder(new TitledBorder(stigmata.getMessages().get("numberofclasses.border")));
199         comparisonCount.setBorder(new TitledBorder(stigmata.getMessages().get("comparisoncount.border")));
200         distinctionRatio.setBorder(new TitledBorder(stigmata.getMessages().get("distinctionratio.border")));
201         average.setBorder(new TitledBorder(stigmata.getMessages().get("average.border")));
202         minimum.setBorder(new TitledBorder(stigmata.getMessages().get("minimum.border")));
203         maximum.setBorder(new TitledBorder(stigmata.getMessages().get("maximum.border")));
204
205         panel.add(south, BorderLayout.SOUTH);
206
207         return panel;
208     }
209
210     private void mdsButtonActionPerformed(ActionEvent e){
211         Map<URL, BirthmarkSet> map = new HashMap<URL, BirthmarkSet>();
212         for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(ExtractionTarget.TARGET_X); i.hasNext(); ){
213             BirthmarkSet bs = i.next();
214             map.put(bs.getLocation(), bs);
215         }
216         for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(ExtractionTarget.TARGET_Y); i.hasNext(); ){
217             BirthmarkSet bs = i.next();
218             map.put(bs.getLocation(), bs);
219         }
220         int index = 0;
221         BirthmarkSet[] set = new BirthmarkSet[map.size()];
222         for(Map.Entry<URL, BirthmarkSet> entry: map.entrySet()){
223             set[index] = entry.getValue();
224             index++;
225         }
226         
227         stigmata.showMdsGraph(set, extraction.getContext());
228     }
229
230     private void graphButtonActionPerformed(ActionEvent e){
231         Map<Integer, Integer> values = new HashMap<Integer, Integer>();
232         for(int i = 0; i < table.getRowCount(); i++){
233             for(int j = 1; j < table.getColumnCount(); j++){
234                 Double d = (Double)table.getValueAt(i, j);
235                 int similarity = (int)Math.round(d.doubleValue() * 100);
236                 Integer dist = values.get(new Integer(similarity));
237                 if(dist == null){
238                     dist = new Integer(0);
239                 }
240                 dist = new Integer(dist.intValue() + 1);
241                 values.put(new Integer(similarity), dist);
242             }
243         }
244         stigmata.showSimilarityDistributionGraph(values);
245     }
246
247     private void initialize(){
248         final Messages messages = stigmata.getMessages();
249         JButton save = GUIUtility.createButton(
250             messages, "savecomparison", new SaveAction(stigmata, new AsciiDataWritable(){
251                 public void writeAsciiData(PrintWriter out, String format){
252                     ResultPrinterSpi service = PrinterManager.getInstance().getService(format);
253                     if(service == null){
254                         service = PrinterManager.getDefaultFormatService();
255                     }
256
257                     service.getComparisonResultSetPrinter().printResult(
258                         out, new RoundRobinComparisonResultSet(extraction)
259                     );
260                 }
261             }
262         ));
263         JButton graph = GUIUtility.createButton(messages, "showgraph");
264         JButton obfuscate = GUIUtility.createButton(messages, "obfuscate");
265         JButton compare = GUIUtility.createButton(messages, "guessedpair");
266         JButton updateColor = GUIUtility.createButton(
267             messages, "updatecellcolor",
268             new UpdateBirthmarkCellColorAction(stigmata, extraction.getEnvironment())
269         );
270         JMenuItem mdsMenu = GUIUtility.createJMenuItem(messages, "mdsmap");
271
272         PopupButton comparePopup = new PopupButton(compare);
273         PopupButton graphPopup = new PopupButton(graph);
274
275         JComponent southPanel = Box.createHorizontalBox();
276
277         setLayout(new BorderLayout());
278         add(getMainPane(), BorderLayout.CENTER);
279         add(southPanel, BorderLayout.SOUTH);
280         southPanel.add(Box.createHorizontalGlue());
281         southPanel.add(save);
282         southPanel.add(Box.createHorizontalGlue());
283         southPanel.add(updateColor);
284         southPanel.add(Box.createHorizontalGlue());
285         southPanel.add(graphPopup);
286         southPanel.add(Box.createHorizontalGlue());
287         southPanel.add(obfuscate);
288         southPanel.add(Box.createHorizontalGlue());
289         southPanel.add(comparePopup);
290         southPanel.add(Box.createHorizontalGlue());
291
292         graph.addActionListener(new ActionListener(){
293             public void actionPerformed(ActionEvent e){
294                 graphButtonActionPerformed(e);
295             }
296         });
297         mdsMenu.addActionListener(new ActionListener(){
298             public void actionPerformed(ActionEvent e){
299                 mdsButtonActionPerformed(e);
300             }
301         });
302
303         obfuscate.addActionListener(new ActionListener(){
304             public void actionPerformed(ActionEvent e){
305                 obfuscateClassNames();
306             }
307         });
308
309         ActionListener compareListener = new ActionListener(){
310             public void actionPerformed(ActionEvent e){
311                 String item = e.getActionCommand();
312                 if(item.equals("guessedpair")){
313                     compareGuessedPair();
314                 }
315                 else if(item.equals("specifiedpair")){
316                     compareSpecifiedPair();
317                 }
318                 else if(item.equals("roundrobin.filtering")){
319                     compareRoundRobinWithFiltering();
320                 }
321             }
322         };
323
324         compare.addActionListener(compareListener);
325         String[] comparisonMethods = stigmata.getMessages().getArray("comparison.methods.inroundrobinresult");
326         for(int i = 1; i < comparisonMethods.length; i++){
327             JMenuItem item = GUIUtility.createJMenuItem(messages, comparisonMethods[i]);
328             comparePopup.addMenuItem(item);
329             item.addActionListener(compareListener);
330         }
331         graphPopup.addMenuItem(mdsMenu);
332     }
333
334     private void compareRoundRobinWithFiltering(){
335         FilterSelectionPane pane = new FilterSelectionPane(
336             stigmata, extraction.getEnvironment().getFilterManager()
337         );
338         int returnValue = JOptionPane.showConfirmDialog(
339             stigmata, pane, stigmata.getMessages().get("filterselection.dialog.title"),
340             JOptionPane.OK_CANCEL_OPTION,
341             JOptionPane.QUESTION_MESSAGE
342         );
343         if(returnValue == JOptionPane.OK_OPTION){
344             String[] filterSetList = pane.getSelectedFilters();
345
346             ComparisonResultSet rs = new RoundRobinComparisonResultSet(extraction);
347             
348             ComparisonResultSet filterResultSet = new FilteredComparisonResultSet(
349                 rs, extraction.getEnvironment().getFilterManager().getFilterSets(filterSetList)
350             );
351             stigmata.showComparisonResultSet(filterResultSet);
352         }
353     }
354
355     private void compareGuessedPair(){
356         ComparisonResultSet rs = new CertainPairComparisonResultSet(extraction);
357         stigmata.showComparisonResultSet(rs);
358     }
359
360     private void compareSpecifiedPair(){
361         File file = stigmata.getOpenFile(
362             stigmata.getMessages().getArray("comparemapping.extension"),
363             stigmata.getMessages().get("comparemapping.description")
364         );
365         if(file != null){
366             Map<String, String> mapping = stigmata.constructMapping(file);
367
368             ComparisonResultSet comparison = new CertainPairComparisonResultSet(extraction, mapping);
369             stigmata.showComparisonResultSet(comparison);
370         }
371     }
372
373     private void obfuscateClassNames(){
374         ClassNameObfuscator obfuscator = new ClassNameObfuscator();
375
376         try{
377             File file = stigmata.getSaveFile(
378                 stigmata.getMessages().getArray("obfuscationmapping.extension"),
379                 stigmata.getMessages().get("obfuscationmapping.description")
380             );
381             if(file != null){
382                 BirthmarkContext context = extraction.getContext();
383                 BirthmarkEnvironment env = context.getEnvironment();
384                 ExtractionResultSet ers = env.getHistoryManager().createDefaultResultSet(context);
385                 try{
386                     for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(ExtractionTarget.TARGET_X); i.hasNext(); ){
387                         BirthmarkSet bs = i.next();
388                         ers.addBirthmarkSet(ExtractionTarget.TARGET_X, obfuscator.obfuscateClassName(bs));
389                     }
390                     for(Iterator<BirthmarkSet> i = extraction.birthmarkSets(ExtractionTarget.TARGET_Y); i.hasNext(); ){
391                         BirthmarkSet bs = i.next();
392                         ers.addBirthmarkSet(ExtractionTarget.TARGET_Y, obfuscator.obfuscateClassName(bs));
393                     }
394                 } catch(BirthmarkStoreException e){
395                 }
396                 this.extraction = ers;
397                 obfuscator.outputNameMappings(file);
398             }
399         }catch(IOException e){
400             JOptionPane.showMessageDialog(
401                 this, e.getMessage(), stigmata.getMessages().get("error.dialog.title"),
402                 JOptionPane.ERROR_MESSAGE
403             );
404             return;
405         }
406
407         DefaultTableModel model = new RoundRobinComparisonResultSetTableModel();
408         compare(model);
409         table.setModel(model);
410         this.model = model;
411     }
412
413     private static class RoundRobinComparisonResultSetTableModel extends DefaultTableModel{
414         private static final long serialVersionUID = 765435324523543242L;
415
416         @Override
417         public boolean isCellEditable(int row, int col){
418             return false;
419         }
420
421         public Class<?> getColumnClass(int column){
422             if(column == 0){
423                 return String.class;
424             }
425             else{
426                 return Double.class;
427             }
428         }
429     }
430 }