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

Commit

Permalink
Merge pull request #19 from CJSCommonPlatform/crc-1531
Browse files Browse the repository at this point in the history
Basic version of JMS endpoint generator (happy path)
  • Loading branch information
purple52 committed Mar 14, 2016
2 parents d0d13be + 3212aca commit 5328304
Show file tree
Hide file tree
Showing 29 changed files with 950 additions and 433 deletions.
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

0 comments on commit 5328304

Please sign in to comment.