/*******************************************************************************
* Copyright (c) 2010 Fraunhofer IWU and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Fraunhofer IWU - initial API and implementation
*******************************************************************************/
package net.enilink.composition.asm;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.FieldNode;
import net.enilink.composition.asm.util.MethodNodeGenerator;
/**
* Represents the mutable structure of a composite class.
*/
public class CompositeClassNode extends ExtendedClassNode {
protected Set<Class<?>> interfaceClassesSet = new LinkedHashSet<Class<?>>();
protected Class<?>[] interfaceClasses;
private Map<List<?>, FieldNode> methodFields = new HashMap<List<?>, FieldNode>();
private int varCount;
public CompositeClassNode(Type type, Class<?> parentClass) {
super(type, parentClass, null);
}
@SuppressWarnings("unchecked")
public void addInterfaceClass(Class<?> face) {
if (interfaceClassesSet.add(face)) {
interfaces.add(Type.getInternalName(face));
interfaceClasses = null;
}
}
public Class<?>[] getInterfacesClasses() {
if (interfaceClasses == null) {
interfaceClasses = interfaceClassesSet
.toArray(new Class<?>[interfaceClassesSet.size()]);
}
return interfaceClasses;
}
@SuppressWarnings("unchecked")
public FieldNode addStaticMethodField(Type declaringClass, String name,
Type returnType, Type[] paramTypes) {
List<?> key = Arrays.asList(declaringClass, name, Arrays
.asList(paramTypes));
FieldNode field = methodFields.get(key);
if (field == null) {
field = new FieldNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
"_$method" + ++varCount, Type.getDescriptor(Method.class),
null, null);
fields.add(field);
methodFields.put(key, field);
MethodNodeGenerator gen = getClassInitGen();
gen.push(declaringClass);
gen.push(name);
gen.loadArray(paramTypes);
gen.invokeVirtual(Type.getType(Class.class),
new org.objectweb.asm.commons.Method("getDeclaredMethod",
Type.getType(Method.class), new Type[] {
Type.getType(String.class),
Type.getType(Class[].class) }));
gen.putStatic(getType(), field.name, Type.getType(field.desc));
}
return field;
}
}