/**
* 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.op;
import java.io.*;
import java.util.Stack;
import java.lang.reflect.*;
import openjava.mop.*;
import openjava.ptree.*;
import mujava.MutationSystem;
/**
* <p>Generate IOR (Overriding method rename) mutants --
* rename the parent's versions of methods that are overridden in a
* subclass so that the overriding does not affect the parents' method
* </p>
* @author Yu-Seung Ma
* @version 1.0
*/
public class IOR extends mujava.op.util.Mutator
{
Stack s;
Class parent_class = null;
FileEnvironment parent_file_env = null;
CompilationUnit parent_comp_unit = null;
/**
* Set parents's version of methods that are overridden in a subclass
* @param file_env
* @param comp_unit
*/
public void setParentEnv(FileEnvironment file_env, CompilationUnit comp_unit)
{
parent_file_env = file_env;
parent_comp_unit = comp_unit;
}
public IOR (FileEnvironment file_env, ClassDeclaration cdecl, CompilationUnit comp_unit)
{
super( file_env,comp_unit );
s = new Stack();
}
public void visit(ClassDeclaration p) throws ParseTreeException
{
s.push(p.getName());
super.visit(p);
s.pop();
}
public void visit(MethodDeclaration p) throws ParseTreeException
{
if (p.getName().equals("main"))
return;
if (isOverridingMethod(p))
{
if (!isIOREquivalent(p))
outputToFile(parent_comp_unit, p);
}
else
{
return;
}
}
boolean isIOREquivalent(MethodDeclaration p)
{
IOR_Equivalent obj = new IOR_Equivalent( parent_file_env, parent_comp_unit );
String str = parent_class.getName();
int index = str.lastIndexOf(".");
if (index >= 0)
{
str = str.substring(index+1, str.length());
}
obj.setInformation(str, p);
try
{
parent_comp_unit.accept(obj);
return (obj.isEquivalent());
} catch (Exception e)
{
e.printStackTrace();
return false;
}
}
boolean isOverridingMethod(MethodDeclaration p)
{
String target_class = comp_unit.getPackage();
for (int i=0; i<s.size(); i++)
{
if (i == 0)
{
if (target_class == null)
{
target_class = s.get(i).toString();
}
else
{
target_class = target_class + "." + s.get(i).toString();
}
}
else
{
target_class = target_class + "$" + s.get(i).toString();
}
}
try
{
parent_class = Class.forName(target_class).getSuperclass();
if ((parent_class == null) || (parent_class.getName().equals("java.lang.Object")))
return false;
Method[] parent_method = parent_class.getDeclaredMethods();
if (parent_method == null)
return false;
for (int i=0; i<parent_method.length; i++)
{
// System.out.println(i + " " + p.getName()+ " : " + parent_method[i].getName());
if (Modifier.isAbstract(parent_method[i].getModifiers()))
continue;
if ( !(parent_method[i].getName().equals(p.getName())) )
continue;
if ( !(parent_method[i].getReturnType().getName().equals(p.getReturnType().getName())) )
continue;
Class[] parent_par = parent_method[i].getParameterTypes();
ParameterList child_parList = p.getParameters();
int size = child_parList.size();
if ( ((parent_par==null) || (parent_par.length==0)) && (size==0) )
{
return true;
}
if (parent_par.length != size)
continue;
boolean isFound = true;
for (int j=0; j<size; j++)
{
// System.out.print(parent_par[j].getName()+" : " + child_parList.get(j).getTypeSpecifier().getName());
if ( !(parent_par[j].getName().equals(child_parList.get(j).getTypeSpecifier().getName())) )
{
isFound = false;
break;
}
}
if (isFound)
return true;
}
return false;
} catch (ClassNotFoundException e)
{
System.out.println(" [Exception at IOD mutant generator]");
e.printStackTrace();
}
return false;
}
String getFileName()
{
// make directory for the mutant
String dir_name = MutationSystem.MUTANT_PATH + "/" + getClassName() + "_" + this.num;
File f = new File(dir_name);
f.mkdir();
String file_name = parent_class.getName();
file_name = file_name.substring(file_name.lastIndexOf(".")+1, file_name.length());
return(dir_name + "/" + file_name + ".java");
}
/**
* Output IOR mutants to files
* @param comp_unit
* @param mutant
*/
public void outputToFile(CompilationUnit comp_unit, MethodDeclaration mutant)
{
if (comp_unit == null)
return;
String f_name;
num++;
f_name = getFileName();
// Change the file name as the name of the child class
String mutant_dir = getMuantID();
try
{
PrintWriter out = getPrintWriter(f_name);
IOR_Writer writer = new IOR_Writer(parent_file_env, mutant_dir, out);
writer.setMutant(mutant);
comp_unit.accept( writer );
out.flush();
out.close();
} catch ( IOException e )
{
System.err.println( "fails to create " + f_name );
} catch ( ParseTreeException e )
{
System.err.println( "errors during printing " + f_name );
e.printStackTrace();
}
}
}