/******************************************************************************* * Copyright (c) 2017 Red Hat. * 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: * Red Hat - Initial Contribution *******************************************************************************/ package org.eclipse.che.api.languageserver.generator; import org.eclipse.lsp4j.jsonrpc.messages.Either; import java.io.PrintWriter; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import static org.eclipse.che.api.languageserver.generator.DtoGenerator.INDENT; import static org.eclipse.che.api.languageserver.generator.DtoGenerator.dtoName; ; /** * This class generates code to convert dto object fields to json properties. * * @author Thomas Mäder */ public class ToJsonGenerator extends ConversionGenerator { private JsonImpl json; public ToJsonGenerator(JsonImpl json) { this.json = json; } public void generateToJson(String indent, PrintWriter out, Class<?> receiverClass, Method m) { String varName = fieldName(m) + "Val"; Type paramType = m.getGenericParameterTypes()[0]; String valueAccess = getterName(receiverClass, m) + "()"; if (getRawClass(paramType).isPrimitive()) { generateToJson(indent, out, varName, getterName(receiverClass, m) + "()", paramType); out.println( String.format(indent + INDENT + "result.%1$s(\"%2$s\", %3$s);", json.put(), fieldName(m), varName)); } else { out.println(indent + String.format("if (%1$s == null) {", valueAccess)); out.println(indent + INDENT + String.format("%1$s((%2$s)null);", m.getName(), paramType.getTypeName())); out.println(indent + "} else {"); generateToJson(indent + INDENT, out, varName, getterName(receiverClass, m) + "()", paramType); out.println( String.format(indent + INDENT + "result.%1$s(\"%2$s\", %3$s);", json.put(), fieldName(m), varName)); out.println(indent + "}"); } } private void generateToJson(String indent, PrintWriter out, String varName, String valueAccess, Type paramType) { if (List.class.isAssignableFrom(getRawClass(paramType))) { new ListConverter(varName, valueAccess, paramType).generateListConversion(indent, out); } else if (Map.class.isAssignableFrom(getRawClass(paramType))) { generateMapConversion(indent, out, varName, valueAccess, paramType); } else if (Either.class.isAssignableFrom(getRawClass(paramType))) { generateEitherConversion(indent, out, varName, valueAccess, paramType); } else { out.println(String.format(indent + "%1$s %2$s = %3$s;", json.element(), varName, jsonValueExpression(getRawClass(paramType), valueAccess))); } } private void generateEitherConversion(String indent, PrintWriter out, String varName, String valueAccess, Type paramType) { String innerName = varName + "e"; out.println(indent + String.format("%1$s %2$s;", json.element(), varName)); out.println(indent + String.format("if (%1$s.getLeft() != null) {", valueAccess)); generateToJson(indent + INDENT, out, innerName, valueAccess + ".getLeft()", EitherUtil.getLeftDisjointType(paramType)); out.println(indent + INDENT + String.format("%1$s= %2$s;", varName, innerName)); out.println(indent + "} else {"); generateToJson(indent + INDENT, out, innerName, valueAccess + ".getRight()", EitherUtil.getRightDisjointType(paramType)); out.println(indent + INDENT + String.format("%1$s= %2$s;", varName, innerName)); out.println(indent + "}"); } private void generateMapConversion(String indent, PrintWriter out, String varName, String valueAccess, Type paramType) { ParameterizedType genericType = (ParameterizedType)paramType; Type valueType = genericType.getActualTypeArguments()[1]; String containedName = varName + "X"; out.println(String.format(indent + "%1$s %2$s = new %1$s();", json.object(), varName)); out.println(String.format(indent + "for (Entry<String, %1$s> %2$s : %3$s.entrySet()) {", valueType.getTypeName(), containedName, valueAccess)); generateToJson(indent + INDENT, out, varName + "Y", containedName + ".getValue()", valueType); out.println(indent + INDENT + String.format("%1$s.%2$s(%3$s.getKey().toString(), %4$s);", varName, json.put(), containedName, varName + "Y")); out.println(indent + "}"); } private String jsonValueExpression(Class<?> paramType, String valueAccess) { if (paramType.isPrimitive()) { return String.format("%1$s;", toJsonConversion(paramType, valueAccess)); } else { return String.format("%1$s == null ? %2$s : %3$s;", valueAccess, json.nullValue(), toJsonConversion(paramType, valueAccess)); } } private String toJsonConversion(Class<?> t, String value) { if (Enum.class.isAssignableFrom(t)) { return String.format("new %1$s(%2$s.name())", json.string(), value); } else if (String.class.isAssignableFrom(t)) { return String.format("new %1$s(%2$s)", json.string(), value); } else if (Number.class.isAssignableFrom(t)) { return String.format("new %1$s(%2$s.doubleValue())", json.number(), value); } else if (t == boolean.class || Boolean.class.isAssignableFrom(t)) { return json.boolValue(value); } else if (isSimpleNumberType(t)) { return String.format("new %1$s(%2$s)", json.number(), value); } else if (t == Object.class) { return String.format("JsonUtil.convertToJson(%1$s)", value); } else { return String.format("((%2$s)%1$s).toJsonElement()", value, dtoName(t)); } } private class ListConverter { private String varName; private String valueAccess; private Type paramType; public ListConverter(String varName, String valueAccess, Type paramType) { this.varName = varName; this.valueAccess = valueAccess; this.paramType = paramType; } private void generateListConversion(String indent, PrintWriter out) { Type containedType = containedType(paramType); String containedName = varName + "X"; out.println(String.format(indent + "%1$s %2$s = new %1$s();", json.array(), varName)); out.println(String.format(indent + "for (%1$s %2$s : %3$s) {", containedType.getTypeName(), containedName, valueAccess)); generateToJson(indent + INDENT, out, varName + "Y", containedName, containedType); out.println(indent + INDENT + json.add(varName, varName + "Y")); out.println(indent + "}"); } } }