/*
* 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.Field;
/**
* Denotes a field to be modified.
* @author Thomas Kerber
* @version 1.0.0
*/
public class FieldModif extends FieldPatch{
private static final long serialVersionUID = 2097120477214527181L;
/**
* The access flags patch.
*/
private final AccessFlagsPatch flagsPatch;
/**
* The patch of the fields signature (type). Null essentially means ID
* patch.
*/
private final String sigPatch;
/**
* The attributes patch.
*/
private final AttributesPatch attribsPatch;
/**
* Creates.
* @param name The fields name.
* @param sigPatch The fields signature patch (null means ID patch,
* everything else replace).
* @param flagsPatch The fields flags patch.
* @param attribsPatch The fields attributes patch.
*/
public FieldModif(String name, String sigPatch,
AccessFlagsPatch flagsPatch, AttributesPatch attribsPatch){
super(name);
this.sigPatch = sigPatch;
this.flagsPatch = flagsPatch;
this.attribsPatch = attribsPatch;
}
/**
* Generates.
* @param old The old field.
* @param new_ The new field.
* @param map The cpool map.
* @return The field patch.
*/
public static FieldModif generate(Field old, Field new_, CPoolMap map){
String name = old.getName();
String sigPatch = new_.getSignature();
if(old.getSignature().equals(sigPatch))
sigPatch = null;
AccessFlagsPatch flagsPatch = AccessFlagsPatch.generate(
old.getAccessFlags(),
new_.getAccessFlags(),
AccessFlagsPatch.AccessLevel.FIELD);
AttributesPatch attribsPatch = AttributesPatch.generate(
old.getAttributes(),
new_.getAttributes(),
map);
return new FieldModif(name, sigPatch, flagsPatch, attribsPatch);
}
/**
*
* @return The patch of the field type. null denotes ID while any other
* value will be used instead.
*/
public String getSignaturePatch(){
return sigPatch;
}
/**
*
* @return The flags patch delegated to.
*/
public AccessFlagsPatch getFlagsPatch(){
return flagsPatch;
}
/**
*
* @return The attributes patch delegated to.
*/
public AttributesPatch getAttributesPatch(){
return attribsPatch;
}
@Override
public Field patch(Field f, CPoolMap map){
if(f == null)
throw new NullPointerException("Cannot modify nonexistant field.");
int flags = flagsPatch.patch(f.getAccessFlags());
String signature = f.getSignature();
if(sigPatch != null)
signature = sigPatch;
List<Attribute> attribs = attribsPatch.patch(
new ArrayList<Attribute>(Arrays.asList(f.getAttributes())),
map);
Attribute[] attribArr = attribs.toArray(new Attribute[attribs.size()]);
int nameIndex = Util.findConstantStringIn(map, name);
int sigIndex = Util.findConstantStringIn(map, signature);
Field newField = new Field(flags, nameIndex, sigIndex, attribArr,
map.to);
return newField;
}
}