Skip to content
This repository has been archived by the owner on Aug 13, 2020. It is now read-only.

Basic version of JMS endpoint generator (happy path) #19

Merged
merged 1 commit into from
Mar 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package uk.gov.justice.services.adapters.test.utils;
package uk.gov.justice.services.adapters.test.utils.builder;

import org.raml.model.Action;
import org.raml.model.ActionType;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package uk.gov.justice.services.adapters.test.utils;
package uk.gov.justice.services.adapters.test.utils.builder;

import org.raml.model.ActionType;
import org.raml.model.Raml;
import org.raml.model.Resource;

import static uk.gov.justice.services.adapters.test.utils.ActionBuilder.action;
import static uk.gov.justice.services.adapters.test.utils.ResourceBuilder.resource;
import static uk.gov.justice.services.adapters.test.utils.builder.ActionBuilder.action;
import static uk.gov.justice.services.adapters.test.utils.builder.ResourceBuilder.resource;

import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -70,4 +70,4 @@ public Raml build() {
raml.setResources(resources);
return raml;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package uk.gov.justice.services.adapters.test.utils;
package uk.gov.justice.services.adapters.test.utils.builder;

import org.raml.model.Action;
import org.raml.model.ActionType;
Expand All @@ -9,6 +9,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static uk.gov.justice.services.adapters.test.utils.builder.ActionBuilder.action;

public class ResourceBuilder {
private final List<ActionBuilder> actionBuilders = new ArrayList<>();
Expand Down Expand Up @@ -61,4 +62,9 @@ public Resource build() {
resource.setActions(actions);
return resource;
}

public ResourceBuilder withDefaultAction() {
with(action().with(ActionType.POST));
return this;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package uk.gov.justice.services.adapters.test.utils;
package uk.gov.justice.services.adapters.test.utils.compiler;

import org.reflections.scanners.SubTypesScanner;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package uk.gov.justice.services.adapters.test.utils;
package uk.gov.justice.services.adapters.test.utils.compiler;

public class CompilationException extends RuntimeException {
private static final long serialVersionUID = 1L;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package uk.gov.justice.services.adapters.test.utils;
package uk.gov.justice.services.adapters.test.utils.compiler;

import com.google.common.collect.Sets;
import org.apache.commons.io.FileUtils;
Expand Down
56 changes: 56 additions & 0 deletions adapters/jms-adapter-generator/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>adapters</artifactId>
<groupId>uk.gov.justice.services</groupId>
<version>0.1.0-SNAPSHOT</version>
</parent>
<artifactId>jms-adapter-generator</artifactId>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>uk.gov.justice</groupId>
<artifactId>raml-generator-core</artifactId>
<version>${raml-maven-plugin.version}</version>
</dependency>
<dependency>
<groupId>org.raml</groupId>
<artifactId>raml-parser</artifactId>
</dependency>
<dependency>
<groupId>uk.gov.justice.services</groupId>
<artifactId>core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>uk.gov.justice.services</groupId>
<artifactId>adapters-test-utils</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package uk.gov.justice.raml.jms.core;

import org.apache.commons.lang.StringUtils;
import org.raml.model.Action;
import org.raml.model.ActionType;
import org.raml.model.Raml;
import org.raml.model.Resource;
import uk.gov.justice.raml.core.Generator;
import uk.gov.justice.raml.core.GeneratorConfig;
import uk.gov.justice.services.core.annotation.Component;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.lang.String.format;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.joining;
import static org.apache.commons.io.FileUtils.write;
import static uk.gov.justice.raml.jms.core.TemplateRenderer.render;

/**
* Generates JMS endpoint classes out of RAML object
*/
public class JmsEndpointGenerator implements Generator {

private static final String UTF_8 = "UTF-8";
private static final String TEMPLATE_LOADING_ERROR = "Failed to load template resource JmsListenerTemplate.tpm";
private static final String ACTIONS_EMPTY_ERROR = "No actions to process";
private static final String OUTPUT_FILE_GENERATION_ERROR = "Failed to create output file for %s";
private static final String FILENAME_POSTFIX = "JmsListener.java";
private static final String JMS_TEMPLATE_RESOURCE = "JmsListenerTemplate.tpm";
private static final Pattern MEDIA_TYPE_PATTERN = Pattern.compile("(application/vnd.)(\\S+)(\\+\\S+)");
private static final String EMPTY = "";

/**
* Generates JMS endpoint classes out of RAML object
*
* @param raml - the RAML object
* @param configuration - contains package of generated sources, as well as source and
* destination folders
*/
@Override
public void run(final Raml raml, final GeneratorConfig configuration) {
final Collection<Resource> ramlResourceModels = raml.getResources().values();
ramlResourceModels.stream()
.map(resource -> templateAttributesFrom(resource, configuration))
.forEach(attribute -> writeToTemplateFile(attribute, jmsListenerTemplate(), outputDirFrom(configuration)));

}

private File outputDirFrom(final GeneratorConfig configuration) {
return new File(format("%s/%s", configuration.getOutputDirectory(),
configuration.getBasePackageName().replace(".", "/")));
}

@SuppressWarnings("resource")
private String jmsListenerTemplate() {
try (final InputStream stream = getClass().getResourceAsStream(JMS_TEMPLATE_RESOURCE)) {
return new Scanner(stream, UTF_8).useDelimiter("\\A").next();
} catch (IOException e) {
throw new JmsEndpointGeneratorException(TEMPLATE_LOADING_ERROR, e);
}
}

private void writeToTemplateFile(final Attributes attributes, final String jmsTemplate,
final File outputDirectory) {
final File file = new File(outputDirectory, createJmsFilenameFrom(attributes.uri));
try {
write(file, render(jmsTemplate, attributes.attributesMap));
} catch (IOException e) {
throw new JmsEndpointGeneratorException(format(OUTPUT_FILE_GENERATION_ERROR, attributes.uri), e);
}
}

private String createJmsFilenameFrom(final String uri) {
return classNameOf(uri) + FILENAME_POSTFIX;
}

/**
* Create Template Attributes from the RAML Resource and Configuration
*
* @param resource RAML Resource
* @param configuration Configuration information
* @return template attributes
*/
private Attributes templateAttributesFrom(final Resource resource, final GeneratorConfig configuration) {
final String uri = resource.getUri();
final HashMap<String, String> data = new HashMap<>();

data.put("PACKAGE_NAME", configuration.getBasePackageName());
data.put("CLASS_NAME", classNameOf(uri));
data.put("ADAPTER_TYPE", componentOf(uri).name());
data.put("DESTINATION_LOOKUP", destinationNameOf(uri));
data.put("MESSAGE_SELECTOR", messageSelectorsFrom(resource.getActions()));

return new Attributes(data, uri);
}

/**
* Convert given URI to a camel cased class name
*
* @param uri URI String to convert
* @return camel case class name
*/
private String classNameOf(final String uri) {
return stream(uri.split("/|\\."))
.map(StringUtils::capitalize)
.collect(joining(EMPTY));
}

/**
* Convert given URI to a valid Component
*
* Takes the last and second to last parts of the URI as the pillar and tier of the Component
*
* @param uri URI String to convert
* @return component the value of the pillar and tier parts of the uri
*/
private Component componentOf(final String uri) {
final String[] uriParts = uri.split("\\.");
return Component.valueOf(uriParts[uriParts.length - 1], uriParts[uriParts.length - 2]);
}

/**
* Construct the destination name from the URI
* @param uri URI String to convert
* @return destination name
*/
private String destinationNameOf(final String uri) {
return uri.replaceAll("/", "");
}

/**
* Parse and format all the message selectors from the Post Action
*
* @param actions Map of ActionType to Action
* @return formatted message selector String
*/
private String messageSelectorsFrom(final Map<ActionType, Action> actions) {
if (actions.isEmpty()) {
throw new JmsEndpointGeneratorException(ACTIONS_EMPTY_ERROR);
}
return format("'%s'", parse(actions.get(ActionType.POST)));
}

/**
* Parse an Action into a message selectors String
*
* @param action Action to parse
* @return formatted message selectors String
*/
private String parse(final Action action) {
return action.getBody().keySet().stream()
.map(this::commandNameOf)
.collect(joining("','"));
}

/**
* Converts media type String to a command name
*
* Command name is equal to everything between "application/vnd." and the first "+".
*
* @param mediaType String representation of the Media Type
* @return command name
*/
private String commandNameOf(final String mediaType) {
final Matcher m = MEDIA_TYPE_PATTERN.matcher(mediaType);
m.find();
return m.group(2);
}

private class Attributes {
final Map<String, String> attributesMap;
final String uri;

public Attributes(final Map<String, String> attributesMap, final String uri) {
this.attributesMap = attributesMap;
this.uri = uri;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package uk.gov.justice.raml.jms.core;

public class JmsEndpointGeneratorException extends RuntimeException {
private static final long serialVersionUID = 1L;

public JmsEndpointGeneratorException(final String message, final Throwable e) {
super(message, e);
}

public JmsEndpointGeneratorException(final String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package uk.gov.justice.raml.jms.core;

import static java.lang.String.format;

import java.util.Map;

import org.apache.commons.lang.text.StrBuilder;

/**
* Basic template rendering class
*
*/
public class TemplateRenderer {
public static final String ATTRIBUTE_KEY_FORMAT = "${%s}";

private TemplateRenderer() {
}

/**
* @param template - string containing template
* @param attributes - attribute keys and values to be used in rendering of the template
* @return - rendered template
*/
public static String render(final String template, final Map<String, String> attributes) {
final StrBuilder stringBuilder = new StrBuilder(template);
attributes.entrySet().forEach(e -> stringBuilder.replaceAll(format(ATTRIBUTE_KEY_FORMAT, e.getKey()), e.getValue()));
return stringBuilder.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ${PACKAGE_NAME};

import javax.inject.Inject;
import javax.ejb.MessageDriven;
import javax.ejb.ActivationConfigProperty;
import uk.gov.justice.services.core.annotation.Adapter;
import uk.gov.justice.services.core.dispatcher.Dispatcher;
import uk.gov.justice.services.core.jms.AbstractJMSListener;
import static uk.gov.justice.services.core.annotation.Component.*;

@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "${DESTINATION_LOOKUP}"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "CPPNAME in(${MESSAGE_SELECTOR})")
})
@Adapter(${ADAPTER_TYPE})
public class ${CLASS_NAME}JmsListener extends AbstractJMSListener {

@Inject
Dispatcher dispatcher;

protected Dispatcher getDispatcher() {
return dispatcher;
}
}
Loading