/******************************************************************************* * Copyright (c) 2012-2017 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.plugin.typescript.dto; import com.google.common.io.Resources; import org.eclipse.che.dto.shared.DTO; import org.eclipse.che.plugin.typescript.dto.model.DtoModel; import org.reflections.Reflections; import org.reflections.scanners.SubTypesScanner; import org.reflections.scanners.TypeAnnotationsScanner; import org.reflections.util.ConfigurationBuilder; import org.stringtemplate.v4.ST; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import static java.nio.charset.StandardCharsets.UTF_8; import static org.reflections.util.ClasspathHelper.forClassLoader; import static org.reflections.util.ClasspathHelper.forJavaClassPath; /** * Write all DTOs found in classpath into a specific file. It will contains both DTO interface and DTO implementation. * It will generate TypeScript code * @author Florent Benoit */ public class TypeScriptDtoGenerator { /** * Name of the template */ public static final String TEMPLATE_NAME = "/".concat(TypeScriptDtoGenerator.class.getPackage().getName().replace(".", "/")).concat("/typescript.template"); /** * String template instance used */ private ST st; /** * Model of DTOs that will be provided to the String Template */ private List<DtoModel> dtoModels; /** * Use of classpath */ private boolean useClassPath; /** * Setup a new generator */ public TypeScriptDtoGenerator() { this.dtoModels = new ArrayList<>(); } public static void main(String[] args) { new TypeScriptDtoGenerator().execute(); } /** * Init stuff is responsible to grab all DTOs found in classpath (classloader) and setup model for String Template */ protected void init() { ConfigurationBuilder configurationBuilder = new ConfigurationBuilder().setScanners(new SubTypesScanner(), new TypeAnnotationsScanner()); if (useClassPath) { configurationBuilder.setUrls(forJavaClassPath()); } else { configurationBuilder.setUrls(forClassLoader()); } // keep only DTO interfaces Reflections reflections = new Reflections(configurationBuilder); List<Class<?>> annotatedWithDtos = new ArrayList<>(reflections.getTypesAnnotatedWith(DTO.class)); List<Class<?>> interfacesDtos = annotatedWithDtos.stream() .filter(clazz -> clazz.isInterface()) .collect(Collectors.toList()); interfacesDtos.stream().forEach(this::analyze); } /** * Analyze a DTO interface by registering the associate model. * @param dto the DTO to analyze */ protected void analyze(Class<?> dto) { // for each dto class, store some data about it this.dtoModels.add(new DtoModel(dto)); } /** * Execute this generator. */ public String execute() { init(); ST template = getTemplate(); template.add("dtos", this.dtoModels); 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; } public void setUseClassPath(boolean useClassPath) { this.useClassPath = useClassPath; } }