/**
* Copyright 2010 Wealthfront Inc. 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 com.kaching.platform.testing;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.transform;
import static com.kaching.platform.common.Strings.format;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.objectweb.asm.Type;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
public class ParsedElements {
public static class ParsedClass implements ParsedElement {
private final String name;
public ParsedClass(String name) {
this.name = name.replace("/", ".");
}
String getPackageName() {
return name.substring(0, name.split("\\$")[0].lastIndexOf('.'));
}
public String getOwner() {
return name.split("\\$")[0];
}
Class<?> load() {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
return null;
}
}
Annotation loadAnnotation(Class<? extends Annotation> annotation) {
Class<?> clazz = load();
if (clazz == null) {
throw new NullPointerException(format("class %s not found", name));
}
return clazz.getAnnotation(annotation);
}
@Override
public String toString() {
return name;
}
@Override
public <T> T visit(ParsedElementVisitor<T> visitor) {
return visitor.caseClass(this);
}
@Override
public int hashCode() {
return Objects.hashCode(name);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ParsedClass that = (ParsedClass) obj;
return name.equals(that.name);
}
}
public static class ParsedConstructor implements ParsedElement {
// TODO
@Override
public <T> T visit(ParsedElementVisitor<T> visitor) {
return visitor.caseConstructor(this);
}
}
public static class ParsedField implements ParsedElement {
private final ParsedClass owner;
private final String name;
public ParsedField(ParsedClass owner, String name) {
this.owner = owner;
this.name = name;
}
Annotation loadAnnotation(Class<? extends Annotation> annotation) {
Field field = load();
if (field == null) {
throw new NullPointerException(format("field %s not found in %s", name, owner));
}
return field.getAnnotation(annotation);
}
public ParsedClass getOwner() {
return owner;
}
Field load() {
Class<?> clazz = owner.load();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.getName().equals(name)) {
return field;
}
}
return null;
}
@Override
public String toString() {
return owner.toString() + "#" + name;
}
@Override
public <T> T visit(ParsedElementVisitor<T> visitor) {
return visitor.caseField(this);
}
@Override
public int hashCode() {
return Objects.hashCode(owner, name);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ParsedField that = (ParsedField) obj;
return
owner.equals(that.owner) &&
name.equals(that.name);
}
}
public static class ParsedMethod implements ParsedElement {
private final ParsedClass owner;
private final String name;
private final String descriptor;
public ParsedMethod(ParsedClass owner, String name, String descriptor) {
this.owner = owner;
this.name = name;
this.descriptor = descriptor;
}
public ParsedClass getOwner() {
return owner;
}
Method load() {
Class<?> clazz = owner.load();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals(name)) {
if (Arrays.equals(Type.getArgumentTypes(method), Type.getArgumentTypes(descriptor))) {
return method;
}
}
}
return null;
}
Annotation loadAnnotation(Class<? extends Annotation> annotation) {
Method method = load();
if (method == null) {
throw new NullPointerException(
format("method %s with signature %s not found in %s", name, descriptor, owner));
}
return method.getAnnotation(annotation);
}
@Override
public String toString() {
return format(
"%s#%s(%s)",
owner.toString(),
name,
Joiner.on(",").join(transform(
newArrayList(Type.getArgumentTypes(descriptor)),
new Function<Type, String>() {
@Override
public String apply(Type from) {
return from.getClassName();
}
})));
}
@Override
public <T> T visit(ParsedElementVisitor<T> visitor) {
return visitor.caseMethod(this);
}
public int hashCode() {
return Objects.hashCode(owner, name, descriptor);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ParsedMethod that = (ParsedMethod) obj;
return
owner.equals(that.owner) &&
name.equals(that.name) &&
descriptor.equals(that.descriptor);
}
}
}