All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.raml.jaxrs.generator.CurrentBuild Maven / Gradle / Ivy

There is a newer version: 3.0.7
Show newest version
/*
 * 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