org.raml.jaxrs.generator.CurrentBuild Maven / Gradle / Ivy
/*
* Copyright 2013-2017 (c) MuleSoft, Inc.
*
* 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 org.raml.jaxrs.generator;
import com.google.common.base.Function;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.FluentIterable;
import com.google.common.io.Files;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.sun.codemodel.JCodeModel;
import org.apache.commons.io.FileUtils;
import org.jsonschema2pojo.GenerationConfig;
import org.raml.jaxrs.generator.builders.*;
import org.raml.jaxrs.generator.builders.resources.ResourceGenerator;
import org.raml.jaxrs.generator.extension.resources.api.*;
import org.raml.jaxrs.generator.ramltypes.GMethod;
import org.raml.jaxrs.generator.ramltypes.GResource;
import org.raml.jaxrs.generator.ramltypes.GResponse;
import org.raml.jaxrs.generator.v10.*;
import org.raml.jaxrs.generator.v10.Annotations;
import org.raml.jaxrs.generator.v10.types.V10RamlToPojoGType;
import org.raml.ramltopojo.*;
import org.raml.ramltopojo.plugin.PluginManager;
import org.raml.v2.api.model.v10.api.Api;
import org.raml.v2.api.model.v10.bodies.Response;
import org.raml.v2.api.model.v10.datamodel.JSONTypeDeclaration;
import org.raml.v2.api.model.v10.datamodel.TypeDeclaration;
import org.raml.v2.api.model.v10.datamodel.XMLTypeDeclaration;
import org.raml.v2.api.model.v10.methods.Method;
import org.raml.v2.api.model.v10.resources.Resource;
import javax.annotation.Nullable;
import javax.lang.model.element.Modifier;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static java.util.Collections.singletonList;
/**
* Created by Jean-Philippe Belanger on 10/26/16. The art of building stuff is here. Factory for building root stuff.
*/
public class CurrentBuild {
private final Api api;
private ExtensionManager extensionManager;
private final List resources = new ArrayList<>();
private final Map builtTypes = new ConcurrentHashMap<>();
private final PluginManager pluginManager = PluginManager.createPluginManager("META-INF/ramltojaxrs-plugin.properties");
private GlobalResourceExtension.Composite resourceExtensionList = new GlobalResourceExtension.Composite();
private Map foundTypes = new HashMap<>();
private final List supportGenerators = new ArrayList<>();
private Configuration configuration;
private Set implementations = new HashSet<>();
private ArrayListMultimap internalTypesPerClass = ArrayListMultimap.create();
private File schemaRepository;
private RamlToPojo ramlToPojo;
public CurrentBuild(Api api, ExtensionManager extensionManager) {
this.api = api;
this.extensionManager = extensionManager;
this.configuration = Configuration.defaultConfiguration();
}
public RamlToPojo fetchRamlToPojoBuilder() {
if (ramlToPojo == null) {
ramlToPojo = RamlToPojoBuilder.builder(this.api)
.inPackage(getModelPackage())
.fetchTypes(TypeFetchers.fromAnywhere())
.build(FluentIterable.from(this.typeConfiguration()).transform(new Function() {
@Nullable
@Override
public String apply(@Nullable String s) {
if (s.contains(".")) {
return s;
} else {
return "core." + s;
}
}
}).toList());
}
return ramlToPojo;
}
public File getSchemaRepository() {
if (schemaRepository == null) {
schemaRepository = Files.createTempDir();
}
return schemaRepository;
}
public Api getApi() {
return api;
}
public String getResourcePackage() {
return configuration.getResourcePackage();
}
public String getModelPackage() {
return configuration.getModelPackage();
}
public String getSupportPackage() {
return configuration.getSupportPackage();
}
public void generate(final File rootDirectory) throws IOException {
try {
if (resources.size() > 0) {
ResponseSupport.buildSupportClasses(rootDirectory, getSupportPackage());
}
for (TypeGenerator typeGenerator : builtTypes.values()) {
if (typeGenerator instanceof RamlToPojoTypeGenerator) {
RamlToPojoTypeGenerator ramlToPojoTypeGenerator = (RamlToPojoTypeGenerator) typeGenerator;
ramlToPojoTypeGenerator.output(new CodeContainer() {
@Override
public void into(ResultingPojos g) throws IOException {
g.createFoundTypes(rootDirectory.getAbsolutePath());
}
});
}
if (typeGenerator instanceof JavaPoetTypeGenerator) {
buildTypeTree(rootDirectory, (JavaPoetTypeGenerator) typeGenerator);
continue;
}
if (typeGenerator instanceof CodeModelTypeGenerator) {
CodeModelTypeGenerator b = (CodeModelTypeGenerator) typeGenerator;
b.output(new CodeContainer() {
@Override
public void into(JCodeModel g) throws IOException {
g.build(rootDirectory);
}
});
}
}
for (ResourceGenerator resource : resources) {
resource.output(new CodeContainer() {
@Override
public void into(TypeSpec g) throws IOException {
JavaFile.Builder file = JavaFile.builder(getResourcePackage(), g).skipJavaLangImports(true);
file.build().writeTo(rootDirectory);
}
});
}
for (JavaPoetTypeGenerator typeGenerator : supportGenerators) {
typeGenerator.output(new CodeContainer() {
@Override
public void into(TypeSpec.Builder g) throws IOException {
JavaFile.Builder file = JavaFile.builder(getSupportPackage(), g.build()).skipJavaLangImports(true);
file.build().writeTo(rootDirectory);
}
});
}
} finally {
if (schemaRepository != null) {
FileUtils.deleteDirectory(schemaRepository);
}
}
}
private void buildTypeTree(final File rootDirectory, final JavaPoetTypeGenerator typeGenerator) throws IOException {
JavaPoetTypeGenerator b = typeGenerator;
b.output(new CodeContainer() {
@Override
public void into(final TypeSpec.Builder containing) throws IOException {
for (final JavaPoetTypeGenerator generator : internalTypesPerClass.get(typeGenerator)) {
generator.output(new CodeContainer() {
@Override
public void into(TypeSpec.Builder g) throws IOException {
g.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
containing.addType(g.build());
}
}, BuildPhase.INTERFACE);
}
if (containing != null) {
JavaFile.Builder file = JavaFile.builder(getModelPackage(), containing.build()).skipJavaLangImports(true);
file.build().writeTo(rootDirectory);
}
}
},
BuildPhase.INTERFACE
);
if (implementations.contains(b)) {
b.output(new CodeContainer() {
@Override
public void into(final TypeSpec.Builder containing) throws IOException {
for (final JavaPoetTypeGenerator generator : internalTypesPerClass.get(typeGenerator)) {
generator.output(new CodeContainer() {
@Override
public void into(TypeSpec.Builder g) throws IOException {
g.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
containing.addType(g.build());
}
}, BuildPhase.IMPLEMENTATION);
}
if (containing != null) {
JavaFile.Builder file = JavaFile.builder(getModelPackage(), containing.build()).skipJavaLangImports(true);
file.build().writeTo(rootDirectory);
}
}
},
BuildPhase.IMPLEMENTATION);
}
}
public void newGenerator(String ramlTypeName, TypeGenerator generator) {
builtTypes.put(ramlTypeName, generator);
}
public void newSupportGenerator(JavaPoetTypeGenerator generator) {
supportGenerators.add(generator);
}
public void newResource(ResourceGenerator rg) {
resources.add(rg);
}
public void constructClasses(GFinder finder) {
TypeFindingListener listener = new TypeFindingListener(foundTypes);
finder.findTypes(listener);
finder.setupConstruction(this);
for (GeneratorType type : foundTypes.values()) {
type.construct(this);
}
}
public List typeConfiguration() {
return Arrays.asList(this.configuration.getTypeConfiguration());
}
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
public GenerationConfig getJsonMapperConfig() {
return configuration.createJsonSchemaGenerationConfig();
}
private void loadBasePlugins(Set plugins, Class pluginType) {
List configuredPlugins = FluentIterable.from(this.typeConfiguration()).transform(new Function() {
@Nullable
@Override
public String apply(@Nullable String s) {
return "ramltojaxrs." + s;
}
}).toList();
for (String basePlugin : configuredPlugins) {
plugins.addAll(pluginManager.getClassesForName(basePlugin, Collections.emptyList(), pluginType));
}
}
public ResourceClassExtension pluginsForResourceClass(Function>, ResourceClassExtension> provider,
GResource resource) {
List data = Annotations.RESOURCE_PLUGINS.get(Collections.emptyList(), api, resource);
Set plugins = buildPluginList(ResourceClassExtension.class, data);
// Ugly, but I don't care
return provider.apply(FluentIterable.from(plugins)
.transform(new Function>() {
@Nullable
@Override
public ResourceClassExtension apply(@Nullable ResourceClassExtension resourceClassExtension) {
return resourceClassExtension;
}
}).toList());
}
public ResponseClassExtension pluginsForResponseClass(Function>, ResponseClassExtension> provider,
GMethod method) {
List data = Annotations.RESPONSE_CLASS_PLUGINS.get(Collections.emptyList(), api, method);
Set plugins = buildPluginList(ResponseClassExtension.class, data);
// Ugly, but I don't care
return provider.apply(FluentIterable.from(plugins)
.transform(new Function>() {
@Nullable
@Override
public ResponseClassExtension apply(@Nullable ResponseClassExtension resourceClassExtension) {
return resourceClassExtension;
}
}).toList());
}
public ResourceMethodExtension pluginsForResourceMethod(Function>, ResourceMethodExtension> provider,
GMethod resource) {
List data = Annotations.METHOD_PLUGINS.get(Collections.emptyList(), api, resource);
Set plugins = buildPluginList(ResourceMethodExtension.class, data);
// Ugly, but I don't care
return provider.apply(FluentIterable.from(plugins)
.transform(new Function>() {
@Nullable
@Override
public ResourceMethodExtension apply(@Nullable ResourceMethodExtension resourceClassExtension) {
return resourceClassExtension;
}
}).toList());
}
public ResponseMethodExtension pluginsForResponseMethod(Function>, ResponseMethodExtension> provider,
GResponse resource) {
List data = Annotations.RESPONSE_PLUGINS.get(Collections.emptyList(), api, resource);
Set plugins = buildPluginList(ResponseMethodExtension.class, data);
// Ugly, but I don't care
return provider.apply(FluentIterable.from(plugins)
.transform(new Function>() {
@Nullable
@Override
public ResponseMethodExtension apply(@Nullable ResponseMethodExtension resourceClassExtension) {
return resourceClassExtension;
}
}).toList());
}
private Set buildPluginList(Class cls, List data) {
Set plugins = new LinkedHashSet<>();
loadBasePlugins(plugins, cls);
for (PluginDef datum : data) {
plugins.addAll(pluginManager.getClassesForName(datum.getPluginName(), datum.getArguments(), cls));
}
return plugins;
}
public Iterable createExtensions(String className) {
try {
Class c = Class.forName(className);
return (Iterable) singletonList(c.newInstance());
} catch (ClassNotFoundException e) {
return FluentIterable.from(extensionManager.getClassesForName(className)).transform(new Function() {
@Nullable
@Override
public T apply(@Nullable Class input) {
try {
return (T) input.newInstance();
} catch (InstantiationException | IllegalAccessException e1) {
throw new GenerationException(e1);
}
}
});
} catch (IllegalAccessException | InstantiationException e) {
throw new GenerationException(e);
}
}
public GlobalResourceExtension withResourceListeners() {
return resourceExtensionList;
}
public V10GType fetchType(Resource implementation, Method method, TypeDeclaration typeDeclaration) {
if (typeDeclaration instanceof JSONTypeDeclaration) {
return (V10GType) ((JsonSchemaTypeGenerator) builtTypes.get(typeDeclaration.type())).getType();
}
if (typeDeclaration instanceof XMLTypeDeclaration) {
return (V10GType) ((XmlSchemaTypeGenerator) builtTypes.get(typeDeclaration.type())).getType();
}
RamlToPojo ramlToPojo = fetchRamlToPojoBuilder();
if (ramlToPojo.isInline(typeDeclaration)) {
TypeName typeName =
ramlToPojo
.fetchType(Names.javaTypeName(implementation, method, typeDeclaration), typeDeclaration);
V10RamlToPojoGType type =
new V10RamlToPojoGType(Names.javaTypeName(implementation, method, typeDeclaration), typeDeclaration);
type.setJavaType(typeName);
return type;
} else {
TypeName typeName =
ramlToPojo
.fetchType(typeDeclaration.type(), typeDeclaration);
V10RamlToPojoGType type = new V10RamlToPojoGType(typeDeclaration.type(), typeDeclaration);
type.setJavaType(typeName);
return type;
}
}
public V10GType fetchType(Resource resource, TypeDeclaration input) {
RamlToPojo ramlToPojo = fetchRamlToPojoBuilder();
if (ramlToPojo.isInline(input)) {
TypeName typeName =
fetchRamlToPojoBuilder()
.fetchType(Names.javaTypeName(resource, input), input);
V10RamlToPojoGType type = new V10RamlToPojoGType(input);
type.setJavaType(typeName);
return type;
} else {
TypeName typeName =
fetchRamlToPojoBuilder()
.fetchType(input.type(), input);
V10RamlToPojoGType type = new V10RamlToPojoGType(input);
type.setJavaType(typeName);
return type;
}
}
public V10GType fetchType(Resource resource, Method method, Response response, TypeDeclaration typeDeclaration) {
if (typeDeclaration instanceof JSONTypeDeclaration) {
return (V10GType) ((JsonSchemaTypeGenerator) builtTypes.get(typeDeclaration.type())).getType();
}
if (typeDeclaration instanceof XMLTypeDeclaration) {
return (V10GType) ((XmlSchemaTypeGenerator) builtTypes.get(typeDeclaration.type())).getType();
}
RamlToPojo ramlToPojo = fetchRamlToPojoBuilder();
if (ramlToPojo.isInline(typeDeclaration)) {
TypeName typeName =
fetchRamlToPojoBuilder()
.fetchType(Names.javaTypeName(resource, method, response, typeDeclaration), typeDeclaration);
V10RamlToPojoGType type =
new V10RamlToPojoGType(Names.javaTypeName(resource, method, response, typeDeclaration), typeDeclaration);
type.setJavaType(typeName);
return type;
} else {
TypeName typeName =
fetchRamlToPojoBuilder()
.fetchType(typeDeclaration.type(), typeDeclaration);
V10RamlToPojoGType type = new V10RamlToPojoGType(typeDeclaration.type(), typeDeclaration);
type.setJavaType(typeName);
return type;
}
}
public V10GType fetchType(String name, TypeDeclaration typeDeclaration) {
TypeName typeName =
fetchRamlToPojoBuilder()
.fetchType(name, typeDeclaration);
V10RamlToPojoGType type = new V10RamlToPojoGType(typeDeclaration);
type.setJavaType(typeName);
return type;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy