/**
* Copyright (C) 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mujava.gui;
import java.io.*;
import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.table.*;
import javax.swing.border.*;
import mujava.MutationSystem;
import mujava.util.DirFileFilter;
import mujava.util.MutantDirFilter;
/**
* <p>Template for viewing mutants: show original source code,
* source code of the selected mutants, summary of mutants </p>
* @author Yu-Seung Ma
* @version 1.0
*/
public abstract class MutantsViewerPanel extends JPanel
{
JComboBox classCB = new JComboBox();
String target_dir = "";
JTable summaryTable = new JTable();
JLabel totalLabel = new JLabel(" Total : " );
JScrollPane summaryPanel = new JScrollPane();
JTextField changeTF = new JTextField(" ");
JScrollPane originalSP = new JScrollPane();
JScrollPane mutantSP = new JScrollPane();
JTextPane originalTP = new JTextPane();
JTextPane mutantTP = new JTextPane();
JList mList = new JList();
SimpleAttributeSet red_attr = new SimpleAttributeSet();
SimpleAttributeSet blue_attr = new SimpleAttributeSet();
SimpleAttributeSet black_attr = new SimpleAttributeSet();
/**
* Initialization
* @throws Exception
*/
void jbInit() throws Exception
{
this.setLayout(new FlowLayout());
StyleConstants.setForeground(red_attr, Color.red);
StyleConstants.setForeground(blue_attr, Color.blue);
StyleConstants.setForeground(black_attr, Color.black);
// summary part:
// for each mutation operators, show the number of mutants generated
// also show the total number of mutants generated
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
JLabel summaryL= new JLabel("* Summary *");
leftPanel.add(summaryL);
initSummaryTable();
summaryTable.setEnabled(false);
summaryPanel.getViewport().add(summaryTable);
setSummaryTableSize();
leftPanel.add(summaryPanel);
leftPanel.add(totalLabel);
summaryPanel.setBorder(new EmptyBorder(1, 1, 1, 1));
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS));
/** ComboBox for class (in which mutants will be generated) selection **/
// Note: For traditional mutants, this section allows the users to
// select a java class file and a method
// For web application, this section allows the users to
// select a java servlet, jsp, htm, or html file
JPanel selectClassPanel = new JPanel();
selectClassPanel.setLayout(new FlowLayout());
JLabel selectClassLabel = new JLabel(" Select a class : ");
selectClassPanel.add(selectClassLabel);
//refreshEnv();
classCB.setEditable(false);
selectClassPanel.add(classCB);
classCB.setPreferredSize(new Dimension(550, 25));
classCB.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
updateClassComboBox();
}
});
JPanel contentPanel = new JPanel();
// show a list of mutants to be selected for viewing
JScrollPane leftContentSP = new JScrollPane();
leftContentSP.getViewport().add(mList, null);
leftContentSP.setPreferredSize(new Dimension(100, 580));
contentPanel.add(leftContentSP);
mList.addMouseListener(new java.awt.event.MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
mList_mouseClicked(e);
}
});
JPanel rightContentPanel = new JPanel();
rightContentPanel.setLayout(new BoxLayout(rightContentPanel, BoxLayout.PAGE_AXIS));
// show the line mutated
changeTF.setPreferredSize(new Dimension(550, 40));
rightContentPanel.add(changeTF);
// show the source code of the original file and the mutant
originalSP.setPreferredSize(new Dimension(550, 270));
mutantSP.setPreferredSize(new Dimension(550, 270));
originalSP.setBorder(new TitledBorder("Original"));
mutantSP.setBorder(new TitledBorder("Mutant"));
mutantSP.getViewport().add(mutantTP, null);
originalSP.getViewport().add(originalTP, null);
rightContentPanel.add(originalSP);
rightContentPanel.add(mutantSP);
contentPanel.add(rightContentPanel);
rightPanel.add(selectClassPanel);
rightPanel.add(Box.createRigidArea(new Dimension(10, 10)));
rightPanel.add(contentPanel);
contentPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
leftPanel.setPreferredSize(new Dimension(100, 500));
this.add(leftPanel);
this.add(rightPanel);
refreshEnv();
}
abstract void setSummaryTableSize();
abstract int getMutantType();
/**
* Check if the source programs are available
* @param str
* @return true -- available, otherwise return false
*/
boolean isProperClass(String str)
{
File f = new File(MutationSystem.MUTANT_HOME, str);
File[] dirs = f.listFiles(new DirFileFilter());
if ((dirs == null) || (dirs.length == 0))
return false;
String[] names = {"", "original"};
switch(getMutantType())
{
case MutationSystem.CM: names[0] = "traditional_mutants";
break;
case MutationSystem.TM: names[0] = "class_mutants";
break;
case MutationSystem.EM: names[0] = "exceptional_mutants";
break;
// case MutationSystem.WM: names[0] = "web_mutants";
// break;
}
for (int i=0; i<names.length; i++)
{
boolean found = false;
for (int j=0; j<dirs.length; j++)
{
if (dirs[j].getName().equals(names[i]))
{
found = true;
break;
}
}
if (!found)
return false;
}
return true;
}
abstract void printGeneratedMutantNum(String[] operators, int[] num);
// name: ������ ����Ʈ �̸���
// ����Ʈ �̸����� �����̼� ������ ���� ����Ѵ�.
void showGeneratedMutantsNum(String[] name)
{
String[] operators = null;
switch(getMutantType())
{
case MutationSystem.CM: operators = MutationSystem.cm_operators; // Ŭ���� ���� �����̼� ������
break;
case MutationSystem.TM: operators = MutationSystem.tm_operators; // �ҵ� ���� �����̼� ������
break;
case MutationSystem.EM: operators = MutationSystem.em_operators; // ���ܻ�Ȳ �����̼� ������
break;
// case MutationSystem.WM: operators = MutationSystem.wm_operators;
// break;
}
int[] num = new int[operators.length]; // �����̼� ������ �� ������ ����
for (int i=0; i<operators.length; i++)
{ // num �迭 �ʱ�ȭ
num[i] = 0;
}
if (name != null)
{
for (int i=0; i<name.length; i++)
{
for (int j=0; j<operators.length; j++)
{ // ==>
if (name[i].indexOf(operators[j]+"_") == 0)
{
num[j]++;
} // ==>
}
}
}
printGeneratedMutantNum(operators, num);
}
/** Change contents for the newly selected class */
void updateClassComboBox()
{
target_dir = classCB.getSelectedItem().toString();
if (target_dir == null) return;
if (isProperClass(target_dir))
{
clearSourceContents();
MutationSystem.setJMutationPaths(target_dir);
updateContents();
}
else
{
clearSourceContents();
mList.setListData(new Vector());
mList.repaint();
showGeneratedMutantsNum(null);
}
this.repaint();
}
abstract void setMutantPath();
abstract String getMutantPath();
void updateContents()
{
setMutantPath();
File mutant_dir = new File(getMutantPath());
String[] mutants = mutant_dir.list(new MutantDirFilter());
showGeneratedMutantsNum(mutants);
mList.setListData(mutants);
mList.repaint();
clearSourceContents();
showOriginal();
}
/** Adjust column size of summary table for generated mutants */
protected void adjustSummaryTableSize(JTable table, AbstractTableModel model)
{
TableColumn column = null;
for (int i = 0; i < table.getColumnCount(); i++)
{
column = table.getColumnModel().getColumn(i);
switch (i)
{
case 0 : column.setMaxWidth(40);
break;
case 1 : column.setMaxWidth(60);
break;
}
}
}
abstract void initSummaryTable();
public void refreshEnv()
{
File f = new File(MutationSystem.MUTANT_HOME);
String[] c_list = f.list(new DirFileFilter());
try
{
classCB.removeAllItems();
}
catch(NullPointerException e)
{ // do nothing???
}
if ( (c_list == null) || (c_list.length == 0) )
{
return;
}
for (int i=0; i<c_list.length; i++)
{
classCB.addItem(c_list[i]);
}
//updateClassComboBox();
this.repaint();
}
abstract void setMutationType();
public void clearSourceContents()
{
try
{
Document ddoc;
ddoc = originalTP.getDocument();
ddoc.remove(0, ddoc.getLength());
ddoc = mutantTP.getDocument();
ddoc.remove(0, ddoc.getLength());
}
catch(BadLocationException e)
{
System.err.println("error " +e);
}
changeTF.setText("");
}
void mList_mouseClicked(MouseEvent e)
{
setMutationType();
Object selected_obj = mList.getSelectedValue();
if (selected_obj != null)
{
String mutant_name = selected_obj.toString();
String mutant_log = getMutantLog(mutant_name);
if (mutant_log != null)
{
System.out.println("MutantsViewerPanel.mList_mouseClicked - mutant_log != null");
showMutant(mutant_name,mutant_log);
}
}
}
/** Show the source code of original Java program */
public void showOriginal()
{
try
{
String strLine;
File myFile = new File(MutationSystem.ORIGINAL_PATH,MutationSystem.CLASS_NAME+".java");
String blank_str;
LineNumberReader lReader = new LineNumberReader(new FileReader(myFile));
Document ddoc = originalTP.getDocument();
while ((strLine=lReader.readLine()) != null)
{
blank_str = "";
int del = (new Integer(lReader.getLineNumber())).toString().length();
for (int k=0; k<5-del; k++)
{
blank_str=blank_str+" ";
}
ddoc.insertString (ddoc.getLength(), lReader.getLineNumber()+blank_str, blue_attr);
ddoc.insertString (ddoc.getLength(), strLine+"\n", black_attr);
}
lReader.close();
} catch (Exception e)
{
System.err.println(" [error] " + e);
}
}
/** Show source code of the selected mutant. Changed part is colored in red
* @param dir_name the name of class (including package name)
* @param changed_line line number of mutated code against original program*/
public void showMutant(String dir_name,int changed_line)
{
System.out.println("MutantsViewerPanel.showMutant - with changed_line");
try
{
Document ddoc = mutantTP.getDocument();
ddoc.remove(0, ddoc.getLength());
int line_num = 0;
int caret_pos = 0;
String strLine;
File myFile = new File(MutationSystem.MUTANT_PATH +
"/" + dir_name, MutationSystem.CLASS_NAME + ".java");
String blank_str;
} catch(Exception e)
{
System.err.println(" [error] " + e);
}
}
/** Show source code of the selected mutant. Changed part is colored in red
* @param dir_name the name of class (including package name)
* @param changed_line line number of mutated code against original program*/
public void showMutant(String dir_name,String mutant_log)
{
System.out.println("MutantsViewerPanel.showMutant (with mutant_log)");
try
{
int changed_line = getMutatedLineNum(mutant_log);
String changed_content = getMutatedContent(mutant_log);
changeTF.setText(" (line " + changed_line + ") " + changed_content);
changeTF.repaint();
Document ddoc = mutantTP.getDocument();
ddoc.remove(0, ddoc.getLength());
int line_num=0;
int caret_pos=0;
String strLine;
File myFile = new File(MutationSystem.MUTANT_PATH +
"/" + dir_name, MutationSystem.CLASS_NAME + ".java");
System.out.println("showMutant: myFile =" + myFile.getAbsolutePath());
String blank_str;
LineNumberReader lReader = new LineNumberReader(new FileReader(myFile));
while ((strLine=lReader.readLine()) != null)
{
blank_str="";
line_num = lReader.getLineNumber();
int del = (new Integer(line_num)).toString().length();
for (int k=0; k<5-del; k++)
{
blank_str = blank_str + " ";
}
ddoc.insertString(ddoc.getLength(), line_num+blank_str, blue_attr);
if (line_num == changed_line)
{
caret_pos = ddoc.getLength();
ddoc.insertString(ddoc.getLength(), strLine + "\n", red_attr);
}
else
{
ddoc.insertString(ddoc.getLength(), strLine + "\n", mutantTP.getCharacterAttributes());
}
}
mutantTP.setCaretPosition(caret_pos);
originalTP.setCaretPosition(caret_pos);
originalTP.repaint();
lReader.close();
} catch(Exception e)
{
System.err.println(" [error] " + e);
}
}
/** Return log for the mutant <i> mutant_name </i> from the log file "mutation_log" <br>
* @return log for the mutant (if no log found, NULL is returned.)*/
String getMutantLog(String mutant_name)
{
try
{
File myFile = new File(MutationSystem.MUTANT_PATH, "mutation_log");
String strLine;
LineNumberReader lReader = new LineNumberReader(new FileReader(myFile));
while ((strLine=lReader.readLine()) != null)
{
if (strLine.indexOf(mutant_name) == 0)
{
return strLine;
}
}
} catch (FileNotFoundException e1)
{
System.err.println(e1);
} catch (IOException e2)
{
System.err.println(e2);
}
return null;
}
/**
* @param name name of the mutant
* @return mutated line for the mutant <i>name</i> */
public int getMutatedLine(String name)
{
try
{
File myFile = new File(MutationSystem.MUTANT_PATH, "mutation_log");
String strLine;
LineNumberReader lReader = new LineNumberReader(new FileReader(myFile));
while ((strLine = lReader.readLine()) != null)
{
if (strLine.indexOf(name) == 0)
{
int changed_line = getMutatedLineNum(strLine);
String changed_content = getMutatedContent(strLine);
changeTF.setText(" (line " + changed_line + ") " + changed_content);
changeTF.repaint();
mutantTP.repaint();
return changed_line;
}
}
changeTF.setText(" ");
} catch (FileNotFoundException e1)
{
System.err.println(e1);
} catch (IOException e2)
{
System.err.println(e2);
}
return -1;
}
int getMutatedLineNum(String str)
{
// MutationSystem.LOG_IDENTIFIER = ":"
int start_index = str.indexOf(MutationSystem.LOG_IDENTIFIER);
// int end_index = str.lastIndexOf(MutationSystem.LOG_IDENTIFIER);
// (Upsorn, 07/14/2009) Modify end_index. Originally, a line of log is formatted as
// mutant_name:line_no:original_string => mutated_string
// In html, it is possible to have <A Href="http://www.ise.gmu.edu/~ofut/classes/632/">
// Thus, for example, log will be recorded as
// WLR_2:28:<A Href="http://www.ise.gmu.edu/~ofut/classes/632/"> ......
// Here, to make the format flexible, consider start_index with the first ":"
// end_index with the second ":"
String log_str = str;
log_str = log_str.substring(start_index+1);
int end_index = start_index + 1 + log_str.indexOf(MutationSystem.LOG_IDENTIFIER);
System.out.println("MutantsViewerPanel.getMutatedLineNum --- " +
"start_index =" + start_index + " : end_index =" + end_index );
String temp = str.substring(start_index + 1, end_index);
return ((new Integer(temp)).intValue());
}
String getMutatedContent(String str)
{
// int end_index = str.lastIndexOf(MutationSystem.LOG_IDENTIFIER);
// (Upsorn, 07/14/2009) Modify end_index. Originally, a line of log is formatted as
// mutant_name:line_no:original_string => mutated_string
// In html, it is possible to have <A Href="http://www.ise.gmu.edu/~ofut/classes/632/">
// Thus, for example, log will be recorded as
// WLR_2:28:<A Href="http://www.ise.gmu.edu/~ofut/classes/632/"> ......
// Here, to make the format flexible, consider start_index with the first ":"
// end_index with the second ":"
// MutationSystem.LOG_IDENTIFIER = ":"
int start_index = str.indexOf(MutationSystem.LOG_IDENTIFIER);
String log_str = str;
log_str = log_str.substring(start_index + 1);
int end_index = start_index + 1 + log_str.indexOf(MutationSystem.LOG_IDENTIFIER);
System.out.println("MutantsViewerPanel.getMutatedContent --- " +
"start_index =" + start_index + " : end_index =" + end_index );
return str.substring(end_index + 1);
}
}