/*******************************************************************************
* Copyright (c) 2012-2015 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.jdt;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
/**
* @author Evgen Vidolob
*/
//todo add support of java8 type annotations
public class TypeBindingConvector {
private static final Gson gson = new GsonBuilder().disableHtmlEscaping().serializeNulls().create();
public static String toJsonBinaryType(SourceTypeBinding binding) {
JsonObject object = new JsonObject();
if(!binding.isAnnotationType()) {
object.add("annotations", toJsonAnnotations(binding.getAnnotations()));
} else
{
object.add("annotations", JsonNull.INSTANCE);
}
object.add("enclosingMethod", null);
object.add("enclosingTypeName", binding.enclosingType() == null ? JsonNull.INSTANCE : new JsonPrimitive(
new String(binding.enclosingType().constantPoolName())));
object.add("fields", toJsonFields(binding.fields()));
object.add("genericSignature",
binding.genericSignature() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(binding.genericSignature())));
object.add("interfaceNames", toJsonInterfaces(binding.superInterfaces()));
object.add("memberTypes", toJsonMemberTypes(binding.memberTypes()));
object.add("methods", toJsonMethods(binding.methods()));
object.add("missingTypeNames", null);
object.add("name",
binding.constantPoolName() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(binding.constantPoolName())));
object.add("sourceName", binding.sourceName() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(binding.sourceName())));
object.add("superclassName",
binding.superclass() == null ? JsonNull.INSTANCE
: new JsonPrimitive(new String(binding.superclass().constantPoolName())));
long annotationTagBits = binding.getAnnotationTagBits();
//remove AreMethodsComplete bit tag from type
annotationTagBits &= ~TagBits.AreMethodsComplete;
object.add("tagBits", new JsonPrimitive(String.valueOf(annotationTagBits)));
object.add("anonymous", new JsonPrimitive(binding.isAnonymousType()));
object.add("local", new JsonPrimitive(binding.isLocalType()));
object.add("member", new JsonPrimitive(binding.isMemberType()));
object.add("sourceFileName",
binding.sourceName() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(binding.sourceName())));
object.add("modifiers", new JsonPrimitive(binding.modifiers));
object.add("binaryType", new JsonPrimitive(true));
object.add("fileName", null);
return gson.toJson(object);
}
private static JsonElement toJsonMethods(MethodBinding[] methods) {
if (methods == null) return JsonNull.INSTANCE;
JsonArray jsonElements = new JsonArray();
for (MethodBinding method : methods) {
jsonElements.add(toJsonMethod(method));
}
return jsonElements;
}
private static JsonElement toJsonMethod(MethodBinding method) {
JsonObject object = new JsonObject();
object.addProperty("modifiers", method.getAccessFlags());
object.addProperty("constructor", method.isConstructor());
object.add("argumentNames", toJsonParametersName(method.sourceMethod()));
object.add("annotations", toJsonAnnotations(method.getAnnotations()));
object.add("defaultValue", toJsonDefaultValue(method.getDefaultValue()));
object.add("exceptionTypeNames", toJsonExceptionTypeNames(method.thrownExceptions));
object.add("genericSignature",
method.genericSignature() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(method.genericSignature())));
object.add("methodDescriptor",
method.signature() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(method.signature())));
object.add("parameterAnnotations", toJsonParameterAnnotations(method));
object.add("selector", method.selector == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(method.selector)));
object.addProperty("tagBits", String.valueOf(method.getAnnotationTagBits()));
object.addProperty("clinit", false);
return object;
}
private static JsonElement toJsonParameterAnnotations(MethodBinding method) {
AnnotationBinding[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations == null) return JsonNull.INSTANCE;
JsonArray array = new JsonArray();
for (AnnotationBinding[] parameterAnnotation : parameterAnnotations) {
array.add(toJsonAnnotations(parameterAnnotation));
}
return array;
}
private static JsonElement toJsonExceptionTypeNames(ReferenceBinding[] thrownExceptions) {
if (thrownExceptions == null) return JsonNull.INSTANCE;
JsonArray array = new JsonArray();
for (ReferenceBinding exception : thrownExceptions) {
array.add(new JsonPrimitive(new String(exception.constantPoolName())));
}
return array;
}
private static JsonElement toJsonDefaultValue(Object defaultValue) {
if (defaultValue == null) return JsonNull.INSTANCE;
JsonObject object = new JsonObject();
if(defaultValue instanceof Constant){
object.add("constant", BinaryTypeConvector.toJsonConstant((Constant)defaultValue));
} else if(defaultValue instanceof TypeBinding) {
object.addProperty("class", new String(((TypeBinding)defaultValue).constantPoolName()));
} else if(defaultValue instanceof AnnotationBinding){
object.add("annotation", toJsonAnnotation((AnnotationBinding)defaultValue));
}else if(defaultValue instanceof FieldBinding){
FieldBinding signature = (FieldBinding)defaultValue;
JsonObject enumSignature = new JsonObject();
enumSignature.addProperty("typeName", new String(signature.type.signature()));
enumSignature.addProperty("constantName", new String(signature.name));
object.add("enum", enumSignature);
}else
if(defaultValue instanceof Object[]) {
JsonArray array = new JsonArray();
for (Object o : (Object[])defaultValue) {
array.add(toJsonDefaultValue(o));
}
object.add("array", array);
}
return object;
}
private static JsonElement toJsonParametersName(AbstractMethodDeclaration parameters) {
if (parameters == null || parameters.arguments == null || parameters.arguments.length == 0) return JsonNull.INSTANCE;
JsonArray array = new JsonArray();
for (Argument parameter : parameters.arguments) {
array.add(new JsonPrimitive(new String(parameter.binding.name)));
}
return array;
}
private static JsonElement toJsonMemberTypes(ReferenceBinding[] memberTypes) {
if (memberTypes == null || memberTypes.length == 0) return null;
JsonArray array = new JsonArray();
for (ReferenceBinding type : memberTypes) {
array.add(toJsonMemberType(type));
}
return array;
}
private static JsonElement toJsonMemberType(ReferenceBinding type) {
JsonObject object = new JsonObject();
object.add("enclosingTypeName",
type.enclosingType() == null ? JsonNull.INSTANCE
: new JsonPrimitive(new String(type.enclosingType().constantPoolName())));
object.addProperty("modifiers", type.modifiers);
object.add("name", type.constantPoolName() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(type.constantPoolName())));
return object;
}
private static JsonElement toJsonInterfaces(ReferenceBinding[] interfaces) {
if (interfaces == null) return JsonNull.INSTANCE;
JsonArray array = new JsonArray();
for (ReferenceBinding anInterface : interfaces) {
array.add(new JsonPrimitive(new String(anInterface.constantPoolName())));
}
return array;
}
private static JsonElement toJsonFields(FieldBinding[] fields) {
if(fields == null || fields.length == 0) return JsonNull.INSTANCE;
JsonArray array = new JsonArray();
for (FieldBinding field : fields) {
array.add(toJsonField(field));
}
return array;
}
private static JsonElement toJsonField(FieldBinding field) {
JsonObject object = new JsonObject();
object.addProperty("modifiers", field.modifiers);
object.add("constant", BinaryTypeConvector.toJsonConstant(field.constant()));
object.add("genericSignature",
field.genericSignature() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(field.genericSignature())));
object.add("name", field.name == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(field.name)));
object.addProperty("tagBits", String.valueOf(field.tagBits));
object.add("typeName", field.type == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(field.type.signature())));
object.add("annotations", toJsonAnnotations(field.getAnnotations()));
return object;
}
private static JsonElement toJsonAnnotations(AnnotationBinding[] annotations) {
if(annotations == null) return JsonNull.INSTANCE;
JsonArray array = new JsonArray();
for (AnnotationBinding annotation : annotations) {
array.add(toJsonAnnotation(annotation));
}
return array;
}
private static JsonElement toJsonAnnotation(AnnotationBinding annotation) {
JsonObject object = new JsonObject();
object.add("typeName",
annotation.getAnnotationType() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(annotation.getAnnotationType().constantPoolName())));
object.add("elementValuePairs", toJsonElementValuePairs(annotation.getElementValuePairs()));
return object;
}
private static JsonElement toJsonElementValuePairs(ElementValuePair[] elementValuePairs) {
if(elementValuePairs == null) return JsonNull.INSTANCE;
JsonArray array = new JsonArray();
for (ElementValuePair pair : elementValuePairs) {
array.add(toJsonElementValuePair(pair));
}
return array;
}
private static JsonElement toJsonElementValuePair(ElementValuePair pair) {
JsonObject object = new JsonObject();
object.add("name", pair.getName() == null ? JsonNull.INSTANCE : new JsonPrimitive(new String(pair.getName())));
object.add("value", toJsonDefaultValue(pair.getValue()));
return object;
}
}