Skip to content

Commit

Permalink
#12132 Add '.d.ts' DTO generator
Browse files Browse the repository at this point in the history
Signed-off-by: Yevhen Vydolob <yvydolob@redhat.com>
  • Loading branch information
evidolob committed Dec 21, 2018
1 parent 7ab424f commit 5cefbf6
Show file tree
Hide file tree
Showing 11 changed files with 412 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public static String convertType(Type type) {
|| Double.TYPE.equals(type)
|| Float.TYPE.equals(type)) {
return "number";
} else if (Boolean.class.equals(type)) {
} else if (Boolean.class.equals(type) || Boolean.TYPE.equals(type)) {
return "boolean";
}

Expand All @@ -147,4 +147,91 @@ public static String convertParametrizedType(
throw new IllegalArgumentException("Invalid type" + type);
}
}

/**
* Same as {@link #convertParametrizedType(Type, ParameterizedType, Type)} but use [] instead if
* 'Array[' for arrays
*/
public static String convertParametrizedTypeDTS(
Type type, ParameterizedType parameterizedType, Type rawType, Type containerType) {

if (List.class.equals(rawType)) {
return convertTypeForDTS(containerType, parameterizedType.getActualTypeArguments()[0]) + "[]";
} else if (Map.class.equals(rawType)) {
return "Map<"
+ convertTypeForDTS(containerType, parameterizedType.getActualTypeArguments()[0])
+ ","
+ convertTypeForDTS(containerType, parameterizedType.getActualTypeArguments()[1])
+ ">";
} else {
throw new IllegalArgumentException("Invalid type" + type);
}
}

/**
* Convert Java type to TypeScript type for .d.ts Same as {@link #convertType(Type)} but in
* addition check if dto and its container dto in same package than skip adding namespace
*/
public static String convertTypeForDTS(Type containerType, Type type) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
return convertParametrizedTypeDTS(type, parameterizedType, rawType, containerType);
} else if (String.class.equals(type) || (type instanceof Class && ((Class) type).isEnum())) {
// Maybe find a better enum type for typescript
return "string";
} else if (Integer.class.equals(type)
|| Integer.TYPE.equals(type)
|| Long.class.equals(type)
|| Long.TYPE.equals(type)
|| Double.class.equals(type)
|| Double.TYPE.equals(type)
|| Float.TYPE.equals(type)) {
return "number";
} else if (Boolean.class.equals(type) || Boolean.TYPE.equals(type)) {
return "boolean";
}

String declarationPackage = convertToDTSPackageName((Class) containerType);
String typePackage = convertToDTSPackageName((Class) type);
if (declarationPackage.equals(typePackage)) {
return convertToDTSName((Class) type);
}

return typePackage + "." + convertToDTSName((Class) type);
}

/** Remove 'Dto' suffix from class nam */
public static String convertToDTSName(Class type) {
String name = type.getSimpleName();
if (name.toLowerCase().endsWith("dto")) {
name = name.substring(0, name.length() - 3);
}

return name;
}

/**
* Convert Java package to TypeScript namespace. This method deletes "org.eclipse.", ".api",
* ".dto", ".shared" segments from dto package name
*
* @param dto
* @return the TS namespace name
*/
public static String convertToDTSPackageName(Class dto) {
return removeSubStrings(dto.getPackage().getName(), "org.eclipse.", ".api", ".dto", ".shared");
}

/** Remove all substrings from original string */
private static String removeSubStrings(String str, String... subStrings) {
StringBuilder builder = new StringBuilder(str);
for (String subString : subStrings) {
int index = builder.indexOf(subString);
if (index != -1) {
builder.delete(index, index + subString.length());
}
}

return builder.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.nio.file.Files;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
Expand Down Expand Up @@ -47,6 +46,10 @@ public class TypeScriptDTOGeneratorMojo extends AbstractMojo {
@Parameter(defaultValue = "${project.build.directory}")
private File targetDirectory;

/** should build new '.d.ts' DTO on old 'ts' DTO interfaces */
@Parameter(defaultValue = "false", property = "dts")
private boolean dts;

@Component private MavenProjectHelper projectHelper;

/** Path to the generated typescript file */
Expand All @@ -56,10 +59,43 @@ public class TypeScriptDTOGeneratorMojo extends AbstractMojo {
private boolean useClassPath;

@Override
public void execute() throws MojoExecutionException, MojoFailureException {
public void execute() throws MojoExecutionException {
if (dts) {
getLog().info("Generating TypeScript DTO d.ts");
generateDTs();
} else {
getLog().info("Generating TypeScript DTO");
generateTs();
}
}

private void generateDTs() throws MojoExecutionException {
TypeScriptDtoDTSGenerator typeScriptDtoGenerator = new TypeScriptDtoDTSGenerator();

getLog().info("Generating TypeScript DTO");
typeScriptDtoGenerator.setUseClassPath(useClassPath);

// define output path for the file to write with typescript definition
String output = typeScriptDtoGenerator.execute();

this.typescriptFile = new File(targetDirectory, project.getArtifactId() + ".d.ts");
File parentDir = this.typescriptFile.getParentFile();
if (!parentDir.exists() && !parentDir.mkdirs()) {
throw new MojoExecutionException(
"Unable to create a directory for writing DTO typescript file '" + parentDir + "'.");
}

try (Writer fileWriter =
Files.newBufferedWriter(this.typescriptFile.toPath(), StandardCharsets.UTF_8)) {
fileWriter.write(output);
} catch (IOException e) {
throw new MojoExecutionException("Cannot write DTO typescript file");
}

// attach this typescript file as maven artifact
projectHelper.attachArtifact(project, "ts", typescriptFile);
}

private void generateTs() throws MojoExecutionException {
TypeScriptDtoGenerator typeScriptDtoGenerator = new TypeScriptDtoGenerator();

typeScriptDtoGenerator.setUseClassPath(useClassPath);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.plugin.typescript.dto;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.io.Resources;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.che.plugin.typescript.dto.model.DtoModel;
import org.eclipse.che.plugin.typescript.dto.model.DtoNamespace;
import org.stringtemplate.v4.ST;

/** Write all DTOs found in classpath into a specific '.d.ts' file */
public class TypeScriptDtoDTSGenerator extends TypeScriptDtoGenerator {

/** Name of the template */
public static final String TEMPLATE_NAME =
"/"
.concat(TypeScriptDtoDTSGenerator.class.getPackage().getName().replace(".", "/"))
.concat("/typescript.d.ts.template");

/** String template instance used */
private ST st;

private Map<String, DtoNamespace> dtoNamespaces = new HashMap<>();

public static void main(String[] args) {
TypeScriptDtoGenerator.main(args);
}

@Override
protected void analyze(Class<?> dto) {
// for each dto class, store some data about it
DtoModel model = new DtoModel(dto);
String namespace = model.getDTSPackageName();
if (!dtoNamespaces.containsKey(namespace)) {
dtoNamespaces.put(namespace, new DtoNamespace(namespace));
}

dtoNamespaces.get(namespace).addModel(model);
}

@Override
public String execute() {
init();
ST template = getTemplate();
template.add("dtoNamespaces", this.dtoNamespaces.values());
String output = template.render();
return output;
}

/**
* Get the template for typescript
*
* @return the String Template
*/
protected ST getTemplate() {
if (st == null) {
URL url = Resources.getResource(TypeScriptDtoGenerator.class, TEMPLATE_NAME);
try {
st = new ST(Resources.toString(url, UTF_8));
} catch (IOException e) {
throw new IllegalArgumentException("Unable to read template", e);
}
}
return st;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,7 @@
*/
package org.eclipse.che.plugin.typescript.dto.model;

import static org.eclipse.che.plugin.typescript.dto.DTOHelper.convertType;
import static org.eclipse.che.plugin.typescript.dto.DTOHelper.getGetterFieldName;
import static org.eclipse.che.plugin.typescript.dto.DTOHelper.getSetterFieldName;
import static org.eclipse.che.plugin.typescript.dto.DTOHelper.getWithFieldName;
import static org.eclipse.che.plugin.typescript.dto.DTOHelper.isDtoGetter;
import static org.eclipse.che.plugin.typescript.dto.DTOHelper.isDtoSetter;
import static org.eclipse.che.plugin.typescript.dto.DTOHelper.isDtoWith;
import static org.eclipse.che.plugin.typescript.dto.DTOHelper.*;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
Expand Down Expand Up @@ -90,7 +84,7 @@ protected void analyze() {
.forEach(
field ->
fieldAttributeModels.add(
new FieldAttributeModel(field.getKey(), field.getValue())));
new FieldAttributeModel(field.getKey(), field.getValue(), dto)));
}

/**
Expand Down Expand Up @@ -154,6 +148,16 @@ public String getPackageName() {
return this.dto.getPackage().getName();
}

/**
* Gets the package name of this interface, without 'dto', 'shared', 'api' sections and
* 'org.eclipse.' prefix
*
* @return the package name of this interface
*/
public String getDTSPackageName() {
return convertToDTSPackageName(this.dto);
}

/**
* Gets the short (simple) name of the interface. Like HelloWorld if FQN class is
* foo.bar.HelloWorld
Expand Down Expand Up @@ -181,4 +185,13 @@ public String getName() {
public List<MethodModel> getMethods() {
return this.methods;
}

/**
* Gets the FQN of this interface like foo.bar.HelloWorld, but without 'Dto' suffix
*
* @return the name of the interface
*/
public String getDtsName() {
return convertToDTSName(this.dto);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.plugin.typescript.dto.model;

import java.util.ArrayList;
import java.util.List;

/** Class for storing all Dto TS namespace interfaces */
public class DtoNamespace {

private final String namespace;
private List<DtoModel> childs = new ArrayList<>();

public DtoNamespace(String namespace) {
this.namespace = namespace;
}

/** @return the namespace name */
public String getNamespace() {
return namespace;
}

/** @return all interfaces that placed in this namespace */
public List<DtoModel> getDtoInterfaces() {
return childs;
}

/**
* Add Dto in this namespace
*
* @param model the dto
*/
public void addModel(DtoModel model) {
childs.add(model);
}
}
Loading

0 comments on commit 5cefbf6

Please sign in to comment.