Java tutorial
/** * 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.github.cchacin; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.tools.generic.DisplayTool; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import java.io.IOException; import java.io.Writer; import java.net.URL; import java.util.Collections; import java.util.Properties; import java.util.Set; public class JsonSchemaProcessor extends AbstractProcessor { private Filer filer; private final VelocityContext vc = new VelocityContext(); private final Template vt; public JsonSchemaProcessor() { super(); final Properties props = new Properties(); final URL url = getClass().getClassLoader().getResource("velocity.properties"); try { props.load(url != null ? url.openStream() : null); } catch (IOException e) { e.printStackTrace(); } final VelocityEngine ve = new VelocityEngine(props); vt = ve.getTemplate("template.vm"); ve.init(); } @Override public Set<String> getSupportedAnnotationTypes() { return Collections.singleton(JsonSchema.class.getCanonicalName()); } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); filer = processingEnv.getFiler(); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { for (final Element element : roundEnv.getElementsAnnotatedWith(JsonSchema.class)) { final TypeElement classElement = (TypeElement) element; final PackageElement packageElement = (PackageElement) classElement.getEnclosingElement(); processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "annotated class: " + classElement.getQualifiedName(), element); final String fqClassName = classElement.getQualifiedName().toString(); final String className = classElement.getSimpleName().toString(); final String packageName = packageElement.getQualifiedName().toString(); final JsonSchema jsonSchema = element.getAnnotation(JsonSchema.class); try { final JsonNode node = new ObjectMapper().readTree( Thread.currentThread().getContextClassLoader().getResourceAsStream(jsonSchema.path())); vc.put("display", new DisplayTool()); vc.put("json", node); vc.put("className", className); vc.put("packageName", packageName); final JavaFileObject jfo = filer.createSourceFile(fqClassName + "JsonSchema"); processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "creating source file: " + jfo.toUri()); final Writer writer = jfo.openWriter(); processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "applying velocity template: " + vt.getName()); vt.merge(vc, writer); writer.close(); } catch (IOException e) { e.printStackTrace(); } } return false; } }