Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
# Conflicts:
#	pom.xml
  • Loading branch information
rolandkrueger committed Jan 7, 2017
2 parents a9432fc + bbd525e commit 91c020e
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 53 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
URI Fragment Routing
====================

[![Build Status](https://travis-ci.org/rolandkrueger/uri-fragment-routing.svg?branch=develop)](https://travis-ci.org/rolandkrueger/uri-fragment-routing) [![Code Coverage](https://img.shields.io/codecov/c/github/rolandkrueger/uri-fragment-routing/develop.svg)](https://codecov.io/github/rolandkrueger/uri-fragment-routing?branch=develop) [![License Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-lightgrey.svg)](https://github.com/rolandkrueger/uri-fragment-routing/blob/master/LICENSE)
[![Build Status](https://travis-ci.org/rolandkrueger/uri-fragment-routing.svg?branch=develop)](https://travis-ci.org/rolandkrueger/uri-fragment-routing) [![Code Coverage](https://img.shields.io/codecov/c/github/rolandkrueger/uri-fragment-routing/develop.svg)](https://codecov.io/github/rolandkrueger/uri-fragment-routing?branch=develop) [![License Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-lightgrey.svg)](https://github.com/rolandkrueger/uri-fragment-routing/blob/master/LICENSE) [ ![Download](https://api.bintray.com/packages/rolandkrueger/maven/uri-fragment-routing/images/download.svg?version=1.0.0) ](https://bintray.com/rolandkrueger/maven/uri-fragment-routing/1.0.0/link)

This library provides a framework for mapping URI fragments as found in URIs such as `http://www.example.com/shop#!signin` on custom actions. For example, the URI fragment `signin` could be mapped on an action class `GoToSignInPageAction` which will be executed when the user visits this address.

Expand Down
49 changes: 29 additions & 20 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>org.roklib</groupId>
<artifactId>uri-fragment-routing</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<packaging>jar</packaging>

<name>URI Fragment Routing Library</name>
Expand Down Expand Up @@ -182,25 +182,6 @@
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<!--variable gpgPath defined in settings.xml-->
<executable>${gpgPath}</executable>
</configuration>
</plugin>
</plugins>
</build>

Expand All @@ -225,4 +206,32 @@
</plugin>
</plugins>
</reporting>

<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<!--variable gpgPath defined in settings.xml-->
<executable>${gpgPath}</executable>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
* <p>
* <h1>Set the routing context</h1> You can define a custom class which is used as the routing context for the {@link
* UriActionMapperTree} object in use. An instance of this class can be passed along with the Uri fragment
* interpretation process with {@link UriActionMapperTree#interpretFragment(String, Object)}. A setter method annotated
* with {@link org.roklib.urifragmentrouting.annotation.RoutingContext} will receive this context object. This method
* must have exactly one argument of the routing context's type.
* interpretation process with {@link UriActionMapperTree#interpretFragment(String, Object, boolean)}. A setter method
* annotated with {@link org.roklib.urifragmentrouting.annotation.RoutingContext} will receive this context object. This
* method must have exactly one argument of the routing context's type.
* <p>
* <h1>Order of invocation for annotated setter methods</h1> When configuring an action class object, the setter methods
* annotated with the annotations described above are invoked in the following order:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
* which can be used for defining link targets in a web application.</li> </ul>
* <p>
* When a URI fragment is to be interpreted by this URI action mapper tree, that fragment has to be passed to method
* {@link #interpretFragment(String)} or {@link #interpretFragment(String, Object)} (the latter method is used when an
* application-specific context object is to be passed along to the URI action command to be found for the URI
* {@link #interpretFragment(String)} or {@link #interpretFragment(String, Object, boolean)} (the latter method is used
* when an application-specific context object is to be passed along to the URI action command to be found for the URI
* fragment). The URI fragment is then split into a token list to be recursively interpreted by the action mappers
* registered on this action mapper tree. Each action mapper is responsible for handling one of the URI tokens which
* represent the individual path segments of the currently interpreted URI fragment.The strategy for splitting a URI
Expand Down Expand Up @@ -96,15 +96,15 @@
* can pass application- and user-specific data to the URI action command. For example, a reference to the current user
* session could be passed along with the routing context.
* <p>
* The routing context object can be specified with {@link #interpretFragment(String, Object)}. <h1>Thread safety</h1>
* The URI fragment routing framework is thread-safe. This means that you typically have one application-scoped instance
* of a {@link UriActionMapperTree} which contains all available URI fragments handled by a single application. In other
* words, it is not necessary to store an instance of {@link UriActionMapperTree} in the user session. <h1>Constructing
* a URI action mapper tree with a builder</h1>There are two options to construct a {@link UriActionMapperTree}: First,
* you can instantiate all action mapper objects yourself, stick them together and add all root action mappers to a
* {@link UriActionMapperTree} with <code>getRootActionMapper().addSubMapper(UriPathSegmentActionMapper)</code>. The
* second option is to use the {@link UriActionMapperTree.UriActionMapperTreeBuilder} to build a URI action mapper tree
* with a fluent API. To start building a URI action mapper tree, you start with the following code:
* The routing context object can be specified with {@link #interpretFragment(String, Object, boolean)}. <h1>Thread
* safety</h1> The URI fragment routing framework is thread-safe. This means that you typically have one
* application-scoped instance of a {@link UriActionMapperTree} which contains all available URI fragments handled by a
* single application. In other words, it is not necessary to store an instance of {@link UriActionMapperTree} in the
* user session. <h1>Constructing a URI action mapper tree with a builder</h1>There are two options to construct a
* {@link UriActionMapperTree}: First, you can instantiate all action mapper objects yourself, stick them together and
* add all root action mappers to a {@link UriActionMapperTree} with <code>getRootActionMapper().addSubMapper(UriPathSegmentActionMapper)</code>.
* The second option is to use the {@link UriActionMapperTree.UriActionMapperTreeBuilder} to build a URI action mapper
* tree with a fluent API. To start building a URI action mapper tree, you start with the following code:
* <pre>
* MapperTreeBuilder builder = UriActionMapperTree.create().buildMapperTree();
* </pre>
Expand Down Expand Up @@ -178,19 +178,37 @@ public void registerSubMapperName(final String subMapperName) {
}

/**
* Interpret the given fragment without using a context object. See {@link #interpretFragment(String, Object)} for
* details.
* Interpret the given fragment without using a context object. See {@link #interpretFragment(String, Object,
* boolean)} for details.
*
* @param uriFragment the URI fragment to be interpreted
*
* @return the command object responsible for the given {@code uriFragment} or {@code null} if the fragment could
* not be resolved to any command class
* @see #interpretFragment(String, Object)
* @see #interpretFragment(String, Object, boolean)
*/
public UriActionCommand interpretFragment(final String uriFragment) {
return interpretFragment(uriFragment, null);
}

/**
* Interpret the given fragment using the specified context object. This method will execute any {@link
* UriActionCommand} found for the given {@code uriFragment} right away. See {@link #interpretFragment(String,
* Object, boolean)} for details.
*
* @param uriFragment the URI fragment to be interpreted
* @param context a custom defined context object which is passed to the action command object via a method
* annotated with {@link org.roklib.urifragmentrouting.annotation.RoutingContext}.
* @param <C> class of the context object
*
* @return the command object responsible for the given {@code uriFragment} or {@code null} if the fragment could
* not be resolved to any command class. Note that this command object has already been executed by this method.
* @see #interpretFragment(String, Object, boolean)
*/
public <C> UriActionCommand interpretFragment(final String uriFragment, final C context) {
return interpretFragment(uriFragment, context, true);
}

/**
* Interpret the given fragment using the specified context object. Interpreting a URI means extracting all URI
* parameter values from the fragment and resolving the fragment to one distinct {@link UriActionCommand} class. If
Expand All @@ -208,15 +226,20 @@ public UriActionCommand interpretFragment(final String uriFragment) {
* annotated with {@link org.roklib.urifragmentrouting.annotation.RoutingContext}. This may be an arbitrary,
* application-defined object, so no restriction is imposed on this object.
*
* @param uriFragment the URI fragment to be interpreted
* @param context an custom defined context object which is passed to the action command object via a method
* annotated with {@link org.roklib.urifragmentrouting.annotation.RoutingContext}.
* @param <C> class of the context object
* @param uriFragment the URI fragment to be interpreted
* @param context a custom defined context object which is passed to the action command object via a method
* annotated with {@link org.roklib.urifragmentrouting.annotation.RoutingContext}.
* @param executeCommand if {@code true}, the {@link UriActionCommand} found for the given URI fragment (if any)
* will be executed right away. If {@code false}, the command object will not be executed but
* only be returned by this method. In this case, the external caller is responsible for
* executing this command.
* @param <C> class of the context object
*
* @return the command object responsible for the given {@code uriFragment} or {@code null} if the fragment could
* not be resolved to any command class. Note that this command object has already been executed by this method.
* not be resolved to any command class. Depending on the given value for parameter {@code executeCommand}, this
* command object will have been executed by this method.
*/
public <C> UriActionCommand interpretFragment(final String uriFragment, final C context) {
public <C> UriActionCommand interpretFragment(final String uriFragment, final C context, final boolean executeCommand) {
final UUID uuid = UUID.randomUUID();
LOG.info("[{}] interpretFragment() - INTERPRET - [ {} ]", uuid, uriFragment);
LOG.debug("[{}] interpreting fragment [ {} ] - PARAMETER_MODE={} - CONTEXT={}", uuid, uriFragment, parameterMode, context);
Expand All @@ -230,11 +253,13 @@ public <C> UriActionCommand interpretFragment(final String uriFragment, final C

if (actionCommandClass != null) {
final UriActionCommand actionCommandObject = createAndConfigureUriActionCommand(uriFragment, context, capturedParameterValues, actionCommandClass);
LOG.debug("[{}] interpretFragment() - Running action command object {}", uuid, actionCommandObject);
actionCommandObject.run();
if (executeCommand) {
LOG.debug("[{}] interpretFragment() - Running action command object {}", uuid, actionCommandObject);
actionCommandObject.run();
}
return actionCommandObject;
}
LOG.debug("[{}] interpretFragment() - No action command class found for fragment", uuid);
LOG.debug("[{}] interpretFragment() - No action command class found for fragment '{}'", uuid, uriFragment);
return null;
}

Expand All @@ -251,7 +276,8 @@ private <C> UriActionCommand createAndConfigureUriActionCommand(final String uri
/**
* Set the parameter mode to be used for interpreting the visited URIs.
*
* @param parameterMode {@link ParameterMode} which will be used by {@link #interpretFragment(String, Object)}
* @param parameterMode {@link ParameterMode} which will be used by {@link #interpretFragment(String, Object,
* boolean)}
*/
private void setParameterMode(final ParameterMode parameterMode) {
this.parameterMode = parameterMode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
/**
* A method annotated with this annotation will receive the routing context object passed to the URI fragment
* interpretation pipeline with {@link org.roklib.urifragmentrouting.UriActionMapperTree#interpretFragment(String,
* Object)}. The routing context is a custom defined object which can be passed along with the interpretation process of
* a URI fragment. This context could be used, for instance, to give the action commands executed at the end of the
* interpretation process access to application services, such as an event bus. This annotation can be used on a method
* in classes implementing {@link org.roklib.urifragmentrouting.UriActionCommand}.
* Object, boolean)}. The routing context is a custom defined object which can be passed along with the interpretation
* process of a URI fragment. This context could be used, for instance, to give the action commands executed at the end
* of the interpretation process access to application services, such as an event bus. This annotation can be used on a
* method in classes implementing {@link org.roklib.urifragmentrouting.UriActionCommand}.
* <p>
* The annotated method is required to have exactly one argument of the same type or a supertype of the context object
* passed into the URI fragment interpretation pipeline with {@link org.roklib.urifragmentrouting.UriActionMapperTree#interpretFragment(String,
* Object)}.
* Object, boolean)}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.List;

import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.Is.isA;
import static org.junit.Assert.assertThat;
import static org.roklib.urifragmentrouting.parameter.ParameterMode.*;

Expand Down Expand Up @@ -68,6 +69,27 @@ public void map_single_path_element_on_action() {
assertThatMyActionCommandWasExecuted();
}

/**
* Test that {@link UriActionMapperTree#interpretFragment(String, Object, boolean)} where the last parameter is
* {@code false} will find the correct URI action command but will not execute it.
* <p>
* Example URL for this case: <tt>http://www.example.com#!home</tt>
*/
@Test
public void test_interpretFragment_when_action_command_is_not_to_be_executed_right_away() throws Exception {
final MapperObjectContainer mappers = new MapperObjectContainer();

mapperTree = UriActionMapperTree.create().buildMapperTree()
.map("home").onAction(MyActionCommand.class)
.finishMapper(mappers::put).build();

final String fragment = assembleFragmentToBeInterpreted(mappers);
final UriActionCommand uriActionCommand = mapperTree.interpretFragment(fragment, context, false);
assertThat((MyActionCommand) uriActionCommand, isA(MyActionCommand.class));
assertThat(context.wasMyActionCommandExecuted, is(false));
assertThat(context.wasDefaultCommandExecuted, is(false));
}

/**
* Maps a nested path element on a URI fragment action.
* <p>
Expand Down

0 comments on commit 91c020e

Please sign in to comment.