/*
* Copyright 2012, Thomas Kerber
*
* 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 milk.jpatch.classLevel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import milk.jpatch.CPoolMap;
import milk.jpatch.Util;
import milk.jpatch.access.AccessFlagsPatch;
import milk.jpatch.attribs.AttributesPatch;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.Method;
/**
* Patch denoting a method being modified.
* @author Thomas Kerber
* @version 1.0.0
*/
public class MethodModif extends MethodPatch{
private static final long serialVersionUID = -9170485812513205093L;
/**
* The component flags patch.
*/
private final AccessFlagsPatch flagsPatch;
/**
* The patch of the return type. Null implies ID patch, anything else a
* replace.
*/
private final String retPatch;
/**
* The component attributes patch.
*/
private final AttributesPatch attribsPatch;
/**
* Creates.
* @param identifier The methods identifier.
* @param retPatch The patch for the methods return type. Null means ID
* patch, anything else a replace patch.
* @param flagsPatch The component flags patch.
* @param attribsPatch The component attributes patch.
*/
public MethodModif(String identifier, String retPatch,
AccessFlagsPatch flagsPatch, AttributesPatch attribsPatch){
super(identifier);
this.retPatch = retPatch;
this.flagsPatch = flagsPatch;
this.attribsPatch = attribsPatch;
}
/**
* Generates.
* @param old The old method.
* @param new_ The new method.
* @param map The cpool map.
* @return The patch.
*/
public static MethodModif generate(Method old, Method new_, CPoolMap map){
String identifier = Util.getMethodIdentifier(old);
String retPatch = Util.getMethodReturn(new_);
if(Util.getMethodReturn(old).equals(retPatch))
retPatch = null;
AccessFlagsPatch flagsPatch = AccessFlagsPatch.generate(
old.getAccessFlags(),
new_.getAccessFlags(),
AccessFlagsPatch.AccessLevel.METHOD);
AttributesPatch attribsPatch = AttributesPatch.generate(
old.getAttributes(),
new_.getAttributes(),
map);
return new MethodModif(identifier, retPatch, flagsPatch, attribsPatch);
}
/**
*
* @return The component flags patch.
*/
public AccessFlagsPatch getFlagsPatch(){
return flagsPatch;
}
/**
*
* @return The return type patch. Null represents ID, anything else a
* replace.
*/
public String getReturnPatch(){
return retPatch;
}
/**
*
* @return The component attributes patch.
*/
public AttributesPatch getAttributesPatch(){
return attribsPatch;
}
@Override
public Method patch(Method m, CPoolMap map){
if(m == null)
throw new NullPointerException(
"Cannot modify nonexistant method.");
int flags = flagsPatch.patch(m.getAccessFlags());
String ret;
if(retPatch != null)
ret = retPatch;
else
ret = Util.getMethodReturn(m);
List<Attribute> attribs = new ArrayList<Attribute>(attribsPatch.patch(
new ArrayList<Attribute>(Arrays.asList(m.getAttributes())),
map));
Attribute[] attribArr = attribs.toArray(new Attribute[attribs.size()]);
int sigIndex = Util.findConstantStringIn(map,
Util.getMethodSig(identifier, ret));
int nameIndex = Util.findConstantStringIn(map, m.getName());
Method newMethod = new Method(flags, nameIndex, sigIndex, attribArr,
map.to);
return newMethod;
}
}