├── gradle.properties ├── jsonhome-examples ├── hellojersey │ ├── src │ │ └── main │ │ │ ├── webapp │ │ │ └── WEB-INF │ │ │ │ ├── .gitignore │ │ │ │ └── web.xml │ │ │ ├── resources │ │ │ ├── de │ │ │ │ └── otto │ │ │ │ │ └── jsonhome │ │ │ │ │ └── jsonhome.properties │ │ │ └── freemarker │ │ │ │ └── jsonhome │ │ │ │ ├── resources.ftl │ │ │ │ ├── directresource.ftl │ │ │ │ └── templatedresource.ftl │ │ │ └── java │ │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ └── example │ │ │ └── hellojersey │ │ │ └── HelloWorldResource.java │ └── build.gradle ├── shop │ ├── src │ │ └── main │ │ │ ├── webapp │ │ │ └── WEB-INF │ │ │ │ ├── properties │ │ │ │ └── shop.properties │ │ │ │ ├── freemarker │ │ │ │ ├── product.ftl │ │ │ │ ├── products.ftl │ │ │ │ └── storefront.ftl │ │ │ │ └── web.xml │ │ │ ├── resources │ │ │ └── docs │ │ │ │ └── rel │ │ │ │ ├── products.md │ │ │ │ └── storefront.md │ │ │ └── java │ │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ └── example │ │ │ ├── storefront │ │ │ └── StorefrontController.java │ │ │ ├── products │ │ │ ├── Product.java │ │ │ └── ProductService.java │ │ │ └── order │ │ │ └── BasketController.java │ └── build.gradle ├── helloworld │ ├── src │ │ └── main │ │ │ ├── webapp │ │ │ └── WEB-INF │ │ │ │ ├── properties │ │ │ │ └── helloworld.properties │ │ │ │ ├── web.xml │ │ │ │ └── spring │ │ │ │ └── helloworld-beans.xml │ │ │ └── java │ │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ └── example │ │ │ └── helloworld │ │ │ └── HelloController.java │ └── build.gradle └── registry │ ├── src │ └── main │ │ ├── webapp │ │ └── WEB-INF │ │ │ ├── properties │ │ │ └── jsonhome-registry.properties │ │ │ └── web.xml │ │ └── resources │ │ └── docs │ │ └── readme.md │ └── build.gradle ├── jsonhome-generator ├── src │ ├── test │ │ ├── resources │ │ │ └── docs │ │ │ │ └── test.md │ │ └── java │ │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ └── generator │ │ │ └── UriTemplateHelperTest.java │ └── main │ │ ├── resources │ │ └── jsonhome │ │ │ ├── css │ │ │ └── jsonhome.css │ │ │ └── freemarker │ │ │ ├── resources.ftl │ │ │ ├── directresource.ftl │ │ │ └── templatedresource.ftl │ │ └── java │ │ └── de │ │ └── otto │ │ └── jsonhome │ │ └── generator │ │ ├── JsonHomeSource.java │ │ ├── UriTemplateHelper.java │ │ └── UriBuilder.java └── build.gradle ├── jsonhome-spring ├── src │ ├── test │ │ ├── resources │ │ │ ├── test │ │ │ │ └── doc │ │ │ │ │ └── test.md │ │ │ └── testSpringContext.xml │ │ └── java │ │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ ├── fixtures │ │ │ └── spring │ │ │ │ ├── TestAspectAnnotation.java │ │ │ │ ├── TestAspectAnnotationAspect.java │ │ │ │ └── TestController.java │ │ │ ├── controller │ │ │ ├── DocControllerTest.java │ │ │ ├── GeneratorBasedJsonHomeSourceTest.java │ │ │ └── HtmlControllerTest.java │ │ │ ├── spring │ │ │ └── SpringControllerTest.java │ │ │ └── generator │ │ │ └── SpringHintsGeneratorTest.java │ └── main │ │ ├── resources │ │ └── spring │ │ │ ├── jsonhome-beans.xml │ │ │ ├── jsonhome-freemarker-beans.xml │ │ │ └── jsonhome-controller-beans.xml │ │ └── java │ │ └── de │ │ └── otto │ │ └── jsonhome │ │ └── generator │ │ ├── SpringHrefVarsGenerator.java │ │ └── SpringJsonHomeGenerator.java └── build.gradle ├── .gitignore ├── lib └── org.markdown │ └── markdown4j-2.2.jar ├── jsonhome-jersey ├── src │ ├── test │ │ ├── resources │ │ │ └── de │ │ │ │ └── otto │ │ │ │ └── jsonhome │ │ │ │ └── jsonhome.properties │ │ └── java │ │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ ├── fixtures │ │ │ ├── two │ │ │ │ ├── Bar.java │ │ │ │ └── Foo.java │ │ │ └── one │ │ │ │ ├── Bar.java │ │ │ │ └── Foo.java │ │ │ ├── JsonHomePropertiesTest.java │ │ │ ├── PATCH.java │ │ │ ├── generator │ │ │ ├── HttpMethodsTest.java │ │ │ └── JerseyResourceLinkGeneratorTest.java │ │ │ └── resource │ │ │ └── scanner │ │ │ └── AnnotationScannerTest.java │ └── main │ │ └── java │ │ └── de │ │ └── otto │ │ └── jsonhome │ │ ├── generator │ │ ├── HttpMethods.java │ │ ├── JerseyHrefVarsGenerator.java │ │ ├── JerseyHintsGenerator.java │ │ ├── JerseyJsonHomeGenerator.java │ │ └── JerseyResourceLinkGenerator.java │ │ ├── resource │ │ ├── Responses.java │ │ ├── JerseyJsonHomeSource.java │ │ ├── scanner │ │ │ └── AnnotationScanner.java │ │ └── RelationResource.java │ │ └── JsonHomeProperties.java └── build.gradle ├── settings.gradle ├── jsonhome-core ├── src │ ├── main │ │ └── java │ │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ ├── model │ │ │ ├── Allow.java │ │ │ ├── Precondition.java │ │ │ ├── Status.java │ │ │ ├── JsonHomeBuilder.java │ │ │ ├── Authentication.java │ │ │ ├── ResourceLink.java │ │ │ └── ResourceLinkHelper.java │ │ │ ├── parser │ │ │ └── JsonHomeParser.java │ │ │ ├── annotation │ │ │ ├── Rel.java │ │ │ ├── Docs.java │ │ │ ├── Href.java │ │ │ ├── Auth.java │ │ │ ├── HrefTemplate.java │ │ │ └── Doc.java │ │ │ └── converter │ │ │ ├── JsonHomeMediaType.java │ │ │ ├── JsonHomeConverter.java │ │ │ └── ResourceLinkConverter.java │ └── test │ │ └── java │ │ └── de │ │ └── otto │ │ └── jsonhome │ │ ├── converter │ │ ├── JsonHomeConverterTest.java │ │ └── ResourceLinkConverterTest.java │ │ └── model │ │ └── ResourceLinkHelperTest.java └── build.gradle ├── jsonhome-client ├── src │ ├── main │ │ └── java │ │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ └── client │ │ │ ├── NotFoundException.java │ │ │ ├── HttpStatusException.java │ │ │ ├── JsonHomeClientException.java │ │ │ ├── SimpleJsonHomeClient.java │ │ │ └── JsonHomeClient.java │ └── test │ │ └── java │ │ └── de │ │ └── otto │ │ └── jsonhome │ │ └── client │ │ ├── SimpleJsonHomeClientTest.java │ │ └── HttpJsonHomeClientTest.java └── build.gradle ├── jsonhome-registry ├── src │ ├── main │ │ └── java │ │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ └── registry │ │ │ ├── controller │ │ │ ├── RegistryJsonHomeSource.java │ │ │ ├── LinkConverter.java │ │ │ ├── RegistriesConverter.java │ │ │ └── RegistryConverter.java │ │ │ └── store │ │ │ ├── InMemoryRegistryRepository.java │ │ │ ├── RegistryRepository.java │ │ │ ├── Link.java │ │ │ └── Registry.java │ └── test │ │ ├── java │ │ └── de │ │ │ └── otto │ │ │ └── jsonhome │ │ │ └── registry │ │ │ ├── fixture │ │ │ ├── LinkFixture.java │ │ │ └── RegistriesFixture.java │ │ │ ├── store │ │ │ └── LinkTest.java │ │ │ └── controller │ │ │ └── RegistryConverterTest.java │ │ └── resources │ │ └── testSpringContext.xml └── build.gradle └── HISTORY.md /gradle.properties: -------------------------------------------------------------------------------- 1 | sonatypeUsername= 2 | sonatypePassword= 3 | -------------------------------------------------------------------------------- /jsonhome-examples/hellojersey/src/main/webapp/WEB-INF/.gitignore: -------------------------------------------------------------------------------- 1 | classes 2 | lib -------------------------------------------------------------------------------- /jsonhome-generator/src/test/resources/docs/test.md: -------------------------------------------------------------------------------- 1 | Hello World! 2 | ============ -------------------------------------------------------------------------------- /jsonhome-spring/src/test/resources/test/doc/test.md: -------------------------------------------------------------------------------- 1 | Test 2 | ==== 3 | 4 | * first 5 | * second -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build 3 | out 4 | *.iml 5 | *.ipr 6 | *.iws 7 | .classpath 8 | .project 9 | .settings 10 | bin -------------------------------------------------------------------------------- /lib/org.markdown/markdown4j-2.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otto-de-legacy/jsonhome/master/lib/org.markdown/markdown4j-2.2.jar -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/resources/de/otto/jsonhome/jsonhome.properties: -------------------------------------------------------------------------------- 1 | applicationBaseUri=http://example.org 2 | relationTypeBaseUri=http://rel.example.org 3 | resource.packages=de.otto.jsonhome.fixtures.one -------------------------------------------------------------------------------- /jsonhome-examples/hellojersey/src/main/resources/de/otto/jsonhome/jsonhome.properties: -------------------------------------------------------------------------------- 1 | applicationBaseUri=http://localhost:8080 2 | relationTypeBaseUri=http://localhost:8080 3 | varTypeBaseUri= 4 | docRootDir= 5 | resource.packages=de.otto.jsonhome.example -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/webapp/WEB-INF/properties/shop.properties: -------------------------------------------------------------------------------- 1 | # Configuration of the properties required by the jsonhome beans: 2 | jsonhome.applicationBaseUri=http://localhost:8081/shop 3 | jsonhome.relationTypeBaseUri=http://localhost:8081/shop 4 | jsonhome.varTypeBaseUri= 5 | jsonhome.docRootDir=/docs/* 6 | -------------------------------------------------------------------------------- /jsonhome-generator/src/main/resources/jsonhome/css/jsonhome.css: -------------------------------------------------------------------------------- 1 | table { margin: 1em; border-collapse: collapse } 2 | td, th { padding: 0.5em; border: 1px #ccc solid; text-align: left } 3 | thead { background: #bee7ff } 4 | tfoot { background: #bee7ff } 5 | ul { margin: 0; padding: 0; list-style: none } 6 | -------------------------------------------------------------------------------- /jsonhome-examples/helloworld/src/main/webapp/WEB-INF/properties/helloworld.properties: -------------------------------------------------------------------------------- 1 | # Configuration of the properties required by the jsonhome beans: 2 | jsonhome.applicationBaseUri=http://localhost:8080/helloworld 3 | jsonhome.relationTypeBaseUri=http://localhost:8080/helloworld 4 | jsonhome.varTypeBaseUri= 5 | jsonhome.docRootDir= -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include "jsonhome-core" 2 | include "jsonhome-generator" 3 | include "jsonhome-jersey" 4 | include "jsonhome-spring" 5 | include "jsonhome-jersey" 6 | include "jsonhome-registry" 7 | include "jsonhome-client" 8 | include "jsonhome-examples/registry" 9 | include "jsonhome-examples/shop" 10 | include "jsonhome-examples/helloworld" 11 | include "jsonhome-examples/hellojersey" 12 | -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/resources/docs/rel/products.md: -------------------------------------------------------------------------------- 1 | It is possible to include Markdown documents into the description of your API, like this one. 2 | 3 | You could add loads of documentation here, including yUML 4 | 5 | %%% yuml 6 | [Customer]<>-orders*>[Order] 7 | [Order]++-0..*>[LineItem] 8 | [Order]-[note:Aggregate root.] 9 | %%% 10 | 11 | See [markdown4j project](http://code.google.com/p/markdown4j/) for details. -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/resources/docs/rel/storefront.md: -------------------------------------------------------------------------------- 1 | /rel/storefront 2 | =============== 3 | 4 | This is an example for a link-relation type defining a link to the storefront of an online shop. 5 | 6 | You could add loads of documentation here, including yUML 7 | 8 | %%% yuml 9 | [Customer]<>-orders*>[Order] 10 | [Order]++-0..*>[LineItem] 11 | [Order]-[note:Aggregate root.] 12 | %%% 13 | 14 | See [markdown4j project](http://code.google.com/p/markdown4j/) for details. -------------------------------------------------------------------------------- /jsonhome-examples/registry/src/main/webapp/WEB-INF/properties/jsonhome-registry.properties: -------------------------------------------------------------------------------- 1 | # Configuration of the properties required by the jsonhome beans: 2 | jsonhome.applicationBaseUri = http://localhost:8082/ 3 | jsonhome.relationTypeBaseUri = http://localhost:8082/ 4 | jsonhome.defaultRegistry = default 5 | jsonhome.varTypeBaseUri= 6 | # The folder in the classpath containing documentation for link-relation types, variables, etc. in markdown format: 7 | # See 8 | jsonhome.docRootDir=/docs/* 9 | -------------------------------------------------------------------------------- /jsonhome-spring/src/main/resources/spring/jsonhome-beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/webapp/WEB-INF/freemarker/product.ftl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Example Shop - Product Details 7 | 8 | 9 | 10 |

Product Details

11 |

Title: ${product.title}

12 |

Price: ${product.price} €

13 | 14 | 15 | -------------------------------------------------------------------------------- /jsonhome-examples/helloworld/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'war' 2 | apply plugin: 'jetty' 3 | apply plugin: 'idea' 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | 9 | dependencies { 10 | compile 'org.springframework:spring-webmvc:4.1.7.RELEASE' 11 | compile 'ch.qos.logback:logback-core:1.1.3' 12 | compile 'ch.qos.logback:logback-classic:1.1.3' 13 | compile project(':jsonhome-spring') 14 | providedCompile 'javax.servlet:javax.servlet-api:3.1.0' 15 | } 16 | 17 | jettyRun.contextPath = '/helloworld' 18 | jettyRun.httpPort = 8080 -------------------------------------------------------------------------------- /jsonhome-examples/registry/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'war' 2 | apply plugin: 'jetty' 3 | 4 | dependencies { 5 | compile 'ch.qos.logback:logback-core:1.1.3' 6 | compile 'ch.qos.logback:logback-classic:1.1.3' 7 | compile project(':jsonhome-core') 8 | compile project(':jsonhome-generator') 9 | compile project(':jsonhome-spring') 10 | compile project(':jsonhome-client') 11 | compile project(':jsonhome-registry') 12 | providedCompile 'javax.servlet:javax.servlet-api:3.1.0' 13 | } 14 | 15 | jettyRun.contextPath = '/' 16 | jettyRun.httpPort = 8082 17 | -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/webapp/WEB-INF/freemarker/products.ftl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Example Shop - Product List 7 | 8 | 9 | 10 |

Lots of wunderful products:

11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /jsonhome-examples/shop/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'war' 2 | apply plugin: 'jetty' 3 | apply plugin: 'idea' 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | 9 | dependencies { 10 | compile 'org.springframework:spring-webmvc:4.1.7.RELEASE' 11 | compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13' 12 | compile 'org.freemarker:freemarker:2.3.23' 13 | compile 'ch.qos.logback:logback-core:1.1.3' 14 | compile 'ch.qos.logback:logback-classic:1.1.3' 15 | compile project(':jsonhome-spring') 16 | providedCompile 'javax.servlet:javax.servlet-api:3.1.0' 17 | } 18 | 19 | jettyRun.contextPath = '/shop' 20 | jettyRun.httpPort = 8081 21 | -------------------------------------------------------------------------------- /jsonhome-examples/helloworld/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | spring-dispatcher 5 | org.springframework.web.servlet.DispatcherServlet 6 | 7 | contextConfigLocation 8 | /WEB-INF/spring/helloworld-beans.xml 9 | 10 | 1 11 | 12 | 13 | 14 | spring-dispatcher 15 | / 16 | 17 | 18 | -------------------------------------------------------------------------------- /jsonhome-examples/registry/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | spring-dispatcher 5 | org.springframework.web.servlet.DispatcherServlet 6 | 7 | contextConfigLocation 8 | /WEB-INF/spring/jsonhome-registry-beans.xml 9 | 10 | 1 11 | 12 | 13 | 14 | spring-dispatcher 15 | / 16 | 17 | 18 | -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | spring-dispatcher 5 | org.springframework.web.servlet.DispatcherServlet 6 | 7 | contextConfigLocation 8 | 9 | /WEB-INF/spring/shop-beans.xml 10 | 11 | 12 | 1 13 | 14 | 15 | 16 | spring-dispatcher 17 | / 18 | 19 | 20 | -------------------------------------------------------------------------------- /jsonhome-examples/hellojersey/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'war' 2 | apply plugin: 'jetty' 3 | apply plugin: 'idea' 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | 9 | dependencies { 10 | compile project(':jsonhome-jersey') 11 | compile 'com.sun.jersey.contribs:jersey-freemarker:1.19' 12 | compile 'com.sun.jersey:jersey-core:1.19' 13 | compile "com.sun.jersey:jersey-json:1.19" 14 | compile 'com.sun.jersey:jersey-server:1.19' 15 | compile 'com.sun.jersey:jersey-servlet:1.19' 16 | compile 'ch.qos.logback:logback-core:1.1.3' 17 | compile 'ch.qos.logback:logback-classic:1.1.3' 18 | 19 | providedCompile 'javax.servlet:javax.servlet-api:3.1.0' 20 | 21 | jettyRun.contextPath = '/hellojersey' 22 | jettyRun.httpPort = 8082 23 | } -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/webapp/WEB-INF/freemarker/storefront.ftl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Example Shop - Storefront 7 | 8 | 9 |

Search for lots of wunderful products:

10 |
11 | 12 | 13 | 14 |
15 |

Documentation of the Example Shop' REST API: REST documentation

16 | 17 | 18 | -------------------------------------------------------------------------------- /jsonhome-examples/registry/src/main/resources/docs/readme.md: -------------------------------------------------------------------------------- 1 | README 2 | ====== 3 | 4 | Lorem ipsum... 5 | 6 | ```json 7 | { 8 | "resources": { 9 | "http://example.org/rel/widgets": { 10 | "href": "/widgets/" 11 | }, 12 | "http://example.org/rel/widget": { 13 | "href-template": "/widgets/{widget_id}", 14 | "href-vars": { 15 | "widget_id": "http://example.org/param/widget" 16 | }, 17 | "hints": { 18 | "allow": ["GET", "PUT", "DELETE", "PATCH"], 19 | "representations": ["application/json"], 20 | "accept-patch": ["application/json-patch"], 21 | "accept-post": ["application/xml"], 22 | "accept-ranges": ["bytes"] 23 | } 24 | } 25 | } 26 | } 27 | ``` -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/java/de/otto/jsonhome/fixtures/two/Bar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.fixtures.two; 18 | 19 | import javax.ws.rs.Path; 20 | 21 | @Path("/bar") 22 | public class Bar { 23 | } 24 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/java/de/otto/jsonhome/fixtures/two/Foo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.fixtures.two; 18 | 19 | import javax.ws.rs.Path; 20 | 21 | @Path("/foo") 22 | public class Foo { 23 | } 24 | -------------------------------------------------------------------------------- /jsonhome-spring/src/test/java/de/otto/jsonhome/fixtures/spring/TestAspectAnnotation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.fixtures.spring; 18 | 19 | import java.lang.annotation.*; 20 | 21 | @Inherited 22 | @Retention(RetentionPolicy.RUNTIME) 23 | @Target(ElementType.METHOD) 24 | public @interface TestAspectAnnotation { 25 | 26 | String value() default ""; 27 | 28 | } -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/java/de/otto/jsonhome/fixtures/one/Bar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.fixtures.one; 18 | 19 | import de.otto.jsonhome.annotation.Rel; 20 | 21 | import javax.ws.rs.GET; 22 | import javax.ws.rs.Path; 23 | 24 | @Path("/bar") @Rel("http://example.org/rel/barType") 25 | public class Bar { 26 | 27 | @GET 28 | public void bar() {}; 29 | } 30 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/model/Allow.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.model; 18 | 19 | /** 20 | * The possible values of allowed HTTP methods. 21 | * 22 | * @author Guido Steinacker 23 | * @since 07.10.12 24 | */ 25 | public enum Allow { 26 | GET, 27 | PUT, 28 | POST, 29 | PATCH, 30 | DELETE, 31 | HEAD, 32 | OPTIONS 33 | } 34 | -------------------------------------------------------------------------------- /jsonhome-client/src/main/java/de/otto/jsonhome/client/NotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.client; 18 | 19 | /** 20 | * @author Guido Steinacker 21 | * @since 27.10.12 22 | */ 23 | public class NotFoundException extends HttpStatusException { 24 | 25 | public NotFoundException(final String message) { 26 | super(404, message); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/java/de/otto/jsonhome/fixtures/one/Foo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.fixtures.one; 18 | 19 | import de.otto.jsonhome.annotation.Rel; 20 | 21 | import javax.ws.rs.POST; 22 | import javax.ws.rs.Path; 23 | 24 | @Path("/foo") @Rel("http://example.org/rel/fooType") 25 | public class Foo { 26 | 27 | @POST 28 | public void foo() {} 29 | 30 | } 31 | -------------------------------------------------------------------------------- /jsonhome-spring/src/main/resources/spring/jsonhome-freemarker-beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | classpath:/jsonhome/freemarker 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /jsonhome-generator/src/main/java/de/otto/jsonhome/generator/JsonHomeSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import de.otto.jsonhome.model.JsonHome; 20 | 21 | /** 22 | * A source for json-home documents. 23 | * 24 | * @author Guido Steinacker 25 | * @since 20.11.12 26 | */ 27 | public interface JsonHomeSource { 28 | 29 | /** 30 | * Returns a JsonHome instance. 31 | * 32 | * @return JsonHome. 33 | */ 34 | public JsonHome getJsonHome(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/java/de/otto/jsonhome/JsonHomePropertiesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome; 18 | 19 | 20 | import org.testng.annotations.Test; 21 | 22 | import java.util.Properties; 23 | 24 | import static org.testng.AssertJUnit.assertEquals; 25 | 26 | public class JsonHomePropertiesTest { 27 | 28 | @Test 29 | public void testReadingProperties() throws Exception { 30 | Properties properties = JsonHomeProperties.getProperties(); 31 | assertEquals(3, properties.size()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/java/de/otto/jsonhome/PATCH.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome; 18 | 19 | import javax.ws.rs.HttpMethod; 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | /** 26 | * Indicates that the annotated method responds to HTTP PATCH requests 27 | * @see javax.ws.rs.HttpMethod 28 | */ 29 | @Target({ElementType.METHOD}) 30 | @Retention(RetentionPolicy.RUNTIME) 31 | @HttpMethod("PATCH") 32 | public @interface PATCH { 33 | } 34 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/generator/HttpMethods.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import javax.ws.rs.HttpMethod; 20 | import java.lang.annotation.Annotation; 21 | 22 | /** 23 | * @author Sebastian Schroeder 24 | * @since 09.12.2012 25 | */ 26 | final class HttpMethods { 27 | 28 | private HttpMethods() {} 29 | 30 | public static boolean isHttpMethod(final Annotation annotation) { 31 | return annotation != null && 32 | annotation.annotationType().getAnnotation(HttpMethod.class) != null; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/resource/Responses.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.resource; 18 | 19 | import javax.ws.rs.core.Response; 20 | 21 | /** 22 | * @author Sebastian Schroeder 23 | * @since 28.12.2012 24 | */ 25 | public final class Responses { 26 | 27 | private Responses() {} 28 | 29 | public static Response addCacheControlHeaders(Response.ResponseBuilder builder, int maxAge) { 30 | return builder. 31 | header("Vary", "Accept"). 32 | header("Cache-Control", "max-age=" + maxAge).build(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /jsonhome-client/src/main/java/de/otto/jsonhome/client/HttpStatusException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.client; 18 | 19 | /** 20 | * @author Guido Steinacker 21 | * @since 27.10.12 22 | */ 23 | public class HttpStatusException extends JsonHomeClientException { 24 | 25 | private final int httpStatusCode; 26 | 27 | public HttpStatusException(final int httpStatusCode, final String message) { 28 | super(message); 29 | this.httpStatusCode = httpStatusCode; 30 | } 31 | 32 | public int getHttpStatusCode() { 33 | return httpStatusCode; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /jsonhome-registry/src/main/java/de/otto/jsonhome/registry/controller/RegistryJsonHomeSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.controller; 18 | 19 | import de.otto.jsonhome.model.JsonHome; 20 | 21 | /** 22 | * A source for json-home documents. 23 | * 24 | * @author Guido Steinacker 25 | * @since 20.11.12 26 | */ 27 | public interface RegistryJsonHomeSource { 28 | 29 | /** 30 | * Returns a JsonHome instance for a specified environment. 31 | * 32 | * The default environment is "". 33 | */ 34 | public JsonHome getJsonHome(String environment); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /jsonhome-spring/src/test/java/de/otto/jsonhome/fixtures/spring/TestAspectAnnotationAspect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.fixtures.spring; 18 | 19 | import org.aspectj.lang.JoinPoint; 20 | import org.aspectj.lang.annotation.Aspect; 21 | import org.aspectj.lang.annotation.Before; 22 | import org.springframework.stereotype.Component; 23 | 24 | @Aspect 25 | @Component 26 | public class TestAspectAnnotationAspect { 27 | 28 | @Before("@target(org.springframework.stereotype.Component) && @annotation(foo)") 29 | public void assertAuthorized(JoinPoint jp, TestAspectAnnotation foo) { 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /jsonhome-client/src/main/java/de/otto/jsonhome/client/JsonHomeClientException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.client; 18 | 19 | /** 20 | * @author Guido Steinacker 21 | * @since 27.10.12 22 | */ 23 | public class JsonHomeClientException extends RuntimeException { 24 | 25 | public JsonHomeClientException(String message) { 26 | super(message); 27 | } 28 | 29 | public JsonHomeClientException(String message, Throwable cause) { 30 | super(message, cause); 31 | } 32 | 33 | public JsonHomeClientException(Throwable cause) { 34 | super(cause); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /jsonhome-examples/hellojersey/src/main/resources/freemarker/jsonhome/resources.ftl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | json-home 7 | 8 | 9 | 10 |

Resource Overview

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | <#list resources as resource> 20 | 21 | 22 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
Link-Relation TypeDocumentation
${resource.linkRelationType} 23 | <#if resource.hints.docs.hasDescription()> 24 | <#list resource.hints.docs.description as doc> 25 | ${doc}
26 | 27 | 28 | <#if resource.hints.docs.hasLink()> 29 | See ${resource.hints.docs.link} 30 | 31 |
 
41 | 42 | 43 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/parser/JsonHomeParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.parser; 18 | 19 | import de.otto.jsonhome.model.JsonHome; 20 | 21 | import java.io.InputStream; 22 | 23 | /** 24 | * JsonHomeParser is used to parse a json-home document and return a JsonHome instance. 25 | * 26 | * @author Guido Steinacker 27 | * @since 26.10.12 28 | */ 29 | public interface JsonHomeParser { 30 | 31 | /** 32 | * Parses the json-home document from an InputStream and returns a JsonHome instance. 33 | * @param stream the stream used to read the json-home document. 34 | * @return JsonHome 35 | */ 36 | public JsonHome parse(final InputStream stream); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /jsonhome-examples/helloworld/src/main/webapp/WEB-INF/spring/helloworld-beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 14 | 20 | 21 | 22 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /jsonhome-registry/src/test/java/de/otto/jsonhome/registry/fixture/LinkFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.fixture; 18 | 19 | import de.otto.jsonhome.registry.store.Link; 20 | 21 | import java.net.URI; 22 | 23 | /** 24 | * @author Guido Steinacker 25 | * @since 11.02.13 26 | */ 27 | public class LinkFixture { 28 | 29 | private LinkFixture() {} 30 | 31 | public static Link registryLink(final String registryName) { 32 | return registryLink(registryName, null); 33 | } 34 | 35 | public static Link registryLink(final String registryName, final String title) { 36 | return new Link( 37 | URI.create("http://example.org/registries/" + registryName), 38 | title); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /jsonhome-examples/hellojersey/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | Jersey REST Service 9 | com.sun.jersey.spi.container.servlet.ServletContainer 10 | 11 | com.sun.jersey.config.property.packages 12 | de.otto.jsonhome.example.hellojersey, 13 | de.otto.jsonhome.resource 14 | 15 | 16 | com.sun.jersey.api.json.POJOMappingFeature 17 | true 18 | 19 | 20 | com.sun.jersey.freemarker.templateBasePath 21 | freemarker 22 | 23 | 1 24 | 25 | 26 | Jersey REST Service 27 | /* 28 | 29 | -------------------------------------------------------------------------------- /jsonhome-spring/src/test/java/de/otto/jsonhome/fixtures/spring/TestController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.fixtures.spring; 18 | 19 | import de.otto.jsonhome.annotation.Rel; 20 | import org.springframework.stereotype.Controller; 21 | import org.springframework.web.bind.annotation.PathVariable; 22 | import org.springframework.web.bind.annotation.RequestMapping; 23 | import org.springframework.web.bind.annotation.ResponseBody; 24 | 25 | @Controller 26 | public class TestController { 27 | 28 | @TestAspectAnnotation 29 | @Rel("/rel/foo") 30 | @RequestMapping(value = "/{fooId}", produces = "text/plain") 31 | @ResponseBody 32 | public String getAFoo(@PathVariable String fooId) { 33 | return fooId; 34 | } 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /jsonhome-generator/src/main/resources/jsonhome/freemarker/resources.ftl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | json-home 7 | 8 | 9 | 10 | 11 |

Resource Overview

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | <#list resources as resource> 21 | 22 | 23 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
Link-Relation TypeDocumentation
${resource.linkRelationType} 24 | <#if resource.hints.docs.hasDescription()> 25 | <#list resource.hints.docs.description as doc> 26 |

${doc}

27 | 28 | 29 | <#if resource.hints.docs.hasLink()> 30 |

See ${resource.hints.docs.link}

31 | 32 |
 
42 | 43 | 44 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/annotation/Rel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.annotation; 17 | 18 | import java.lang.annotation.*; 19 | 20 | /** 21 | * Specifies the link-relation type of the resource offered by the annotated controller-class or method. 22 | * 23 | * All resources with a link-relation type will be part of the generated json-home document. Resources 24 | * without a link-relation type will NOT be added to the json-home. 25 | * 26 | * @author Guido Steinacker 27 | * @since 15.09.12 28 | */ 29 | @Target({ElementType.METHOD, ElementType.TYPE}) 30 | @Retention(RetentionPolicy.RUNTIME) 31 | @Documented 32 | public @interface Rel { 33 | 34 | /** 35 | * The URI uniquely identifying the link relation type in a given context. 36 | * 37 | * 38 | * @return URI of the link relation type 39 | */ 40 | String value(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /jsonhome-examples/hellojersey/src/main/java/de/otto/jsonhome/example/hellojersey/HelloWorldResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.example.hellojersey; 18 | 19 | import de.otto.jsonhome.annotation.Doc; 20 | import de.otto.jsonhome.annotation.Rel; 21 | 22 | import javax.ws.rs.GET; 23 | import javax.ws.rs.Path; 24 | import javax.ws.rs.Produces; 25 | import javax.ws.rs.core.MediaType; 26 | import javax.ws.rs.core.Response; 27 | 28 | /** 29 | * @author Sebastian Schroeder 30 | * @since 11.12.2012 31 | */ 32 | @Path("/") 33 | @Rel("/rel/hello-world-example") 34 | @Doc(rel = "/rel/hello-world-example", 35 | value = "The hello-world example resource" 36 | ) 37 | public class HelloWorldResource { 38 | 39 | @GET 40 | @Produces(MediaType.TEXT_PLAIN) 41 | public Response helloWorld() { 42 | return Response.ok("Hello World!").build(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/JsonHomeProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome; 18 | 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.util.Properties; 22 | 23 | /** 24 | * @author Sebastian Schroeder 25 | * @since 15.12.2012 26 | */ 27 | public final class JsonHomeProperties { 28 | 29 | private JsonHomeProperties() {} 30 | 31 | public static Properties getProperties() { 32 | final InputStream is = JsonHomeProperties.class.getResourceAsStream("jsonhome.properties"); 33 | final Properties properties = new Properties(); 34 | if (is == null) { 35 | return properties; 36 | } else { 37 | try { 38 | properties.load(is); 39 | is.close(); 40 | } catch (IOException e) {} 41 | } 42 | return properties; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /jsonhome-examples/hellojersey/src/main/resources/freemarker/jsonhome/directresource.ftl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | json-home 7 | 8 | 9 |

${resource.linkRelationType}

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | <#include "hints-rows.ftl"/> 40 | 41 | 42 | 43 | 44 | 45 | 46 |
AttributeValueDescription
Rel${resource.linkRelationType} 24 | <#if resource.hints.docs.hasDescription()> 25 | <#list resource.hints.docs.description as doc> 26 | ${doc}
27 | 28 | 29 | <#if resource.hints.docs.hasLink()> 30 | See ${resource.hints.docs.link} 31 | 32 |
Href${resource.href}The href link to the resource.
 
47 | 48 | -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/java/de/otto/jsonhome/example/storefront/StorefrontController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.example.storefront; 17 | 18 | import de.otto.jsonhome.annotation.Doc; 19 | import de.otto.jsonhome.annotation.Rel; 20 | import org.springframework.stereotype.Controller; 21 | import org.springframework.web.bind.annotation.RequestMapping; 22 | 23 | 24 | /** 25 | * Controller used to handle the /storefront resource of our example web-shop application. 26 | * 27 | * @author Guido Steinacker 28 | * @since 15.09.12 29 | */ 30 | @Controller 31 | @RequestMapping(value = "/storefront") 32 | @Rel("/rel/storefront") 33 | @Doc(rel = "/rel/storefront", 34 | link = "docs/rel/storefront.md" 35 | ) 36 | public class StorefrontController { 37 | 38 | @RequestMapping(produces = "text/html") 39 | public String getStorefront() { 40 | return "storefront"; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/java/de/otto/jsonhome/generator/HttpMethodsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | 20 | import org.testng.annotations.Test; 21 | 22 | import javax.ws.rs.GET; 23 | 24 | import static org.testng.AssertJUnit.assertFalse; 25 | import static org.testng.AssertJUnit.assertTrue; 26 | 27 | public class HttpMethodsTest { 28 | 29 | class GetAnnotation { 30 | 31 | @GET 32 | public String getMethod() { 33 | return ""; 34 | } 35 | 36 | } 37 | 38 | @Test 39 | public void testGetAnnotation() throws Exception { 40 | assertTrue(HttpMethods.isHttpMethod(GetAnnotation.class. 41 | getMethod("getMethod").getAnnotation(GET.class))); 42 | } 43 | 44 | @Test 45 | public void testNullAnnotation() throws Exception { 46 | assertFalse(HttpMethods.isHttpMethod(null)); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/annotation/Docs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.annotation; 17 | 18 | import java.lang.annotation.*; 19 | 20 | /** 21 | * A container annotation used to add documentation of multiple link-relation types to a single controller. 22 | * 23 | * Usage: 24 | * {@code 25 | * @Documentation({ 26 | * @Doc(rel="/rel/foo-type", value="A reference to a foo"), 27 | * @Doc(rel="/rel/bar-type", value="A reference to a bar") 28 | * }) 29 | * } 30 | * 31 | * 32 | * @author Guido Steinacker 33 | * @since 15.09.12 34 | */ 35 | @Target(ElementType.TYPE) 36 | @Retention(RetentionPolicy.RUNTIME) 37 | @Documented 38 | public @interface Docs { 39 | 40 | /** 41 | * One or more RelDoc annotations, describing link-relation types. 42 | * 43 | * @return array of RelDoc annotations. 44 | */ 45 | Doc[] value(); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/model/Precondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.model; 18 | 19 | /** 20 | * @author Guido Steinacker 21 | * @since 15.10.12 22 | */ 23 | public enum Precondition { 24 | 25 | NONE(""), ETAG("etag"), LAST_MODIFIED("last-modified"); 26 | 27 | private final String representation; 28 | 29 | private Precondition(final String representation) { 30 | this.representation = representation; 31 | } 32 | 33 | public static Precondition preconditionOf(final String value) { 34 | for (final Precondition precondition : Precondition.values()) { 35 | if (precondition.toString().equals(value)) { 36 | return precondition; 37 | } 38 | } 39 | throw new IllegalArgumentException("Unknown precondition " + value); 40 | } 41 | 42 | public String toString() { 43 | return representation; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/annotation/Href.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.annotation; 17 | 18 | import java.lang.annotation.*; 19 | 20 | /** 21 | * Overrides the href of a direct resource link. 22 | * 23 | * Use this annotation if you have to override the behaviour of the generator in use (like, for example, 24 | * the SpringJsonHomeGenerator). Generally, you should not use this annotation, because 25 | * if you are specifying the wrong URI, the href link in your json-home will be resolvable by your application. 26 | * 27 | * @author Guido Steinacker 28 | * @since 15.09.12 29 | */ 30 | @Target(ElementType.METHOD) 31 | @Retention(RetentionPolicy.RUNTIME) 32 | @Documented 33 | public @interface Href { 34 | 35 | /** 36 | * The fully qualified or relative URI uniquely identifying the href of a linked resource. 37 | * 38 | * @return URI of the linked resource 39 | */ 40 | String value(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/annotation/Auth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.annotation; 17 | 18 | import java.lang.annotation.Documented; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 24 | 25 | /** 26 | * Information about the authentication scheme of a HTTP resource described in the Hints. 27 | * 28 | * @author Guido Steinacker 29 | * @since 15.09.12 30 | */ 31 | @Target({ANNOTATION_TYPE}) 32 | @Retention(RetentionPolicy.RUNTIME) 33 | @Documented 34 | public @interface Auth { 35 | 36 | /** 37 | * The scheme used for authentication 38 | * 39 | * @return authenticat scheme 40 | */ 41 | String scheme() default ""; 42 | 43 | 44 | /** 45 | * The realms used for authentication 46 | * 47 | * @return authentication realms 48 | */ 49 | String[] realms() default {}; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/java/de/otto/jsonhome/example/products/Product.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.example.products; 17 | 18 | import java.util.UUID; 19 | 20 | /** 21 | * A product, having only a few attributes. 22 | * 23 | * @author Guido Steinacker 24 | * @since 29.09.12 25 | */ 26 | public final class Product { 27 | private final long id; 28 | private final String title; 29 | private final String price; 30 | private final String etag; 31 | 32 | public Product(final long id, final String title, final String price) { 33 | this.id = id; 34 | this.title = title; 35 | this.price = price; 36 | this.etag = UUID.randomUUID().toString(); 37 | } 38 | 39 | public long getId() { 40 | return id; 41 | } 42 | 43 | public String getLink() { 44 | return "products/" + id; 45 | } 46 | 47 | public String getTitle() { 48 | return title; 49 | } 50 | 51 | public String getPrice() { 52 | return price; 53 | } 54 | 55 | public String getETag() { 56 | return etag; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /jsonhome-spring/src/test/resources/testSpringContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | http://example.org 13 | http://specs.example.org 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/model/Status.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.model; 18 | 19 | /** 20 | * Status of the linked resource. 21 | * 22 | * @author Guido Steinacker 23 | * @since 15.10.12 24 | */ 25 | public enum Status { 26 | /** The resource is available. */ 27 | OK, 28 | /** The resource is deprecated and should not be used anymore. */ 29 | DEPRECATED, 30 | /** The resource is gone, request will be answered as HTTP 410 gone. */ 31 | GONE; 32 | 33 | /** 34 | * Merges this status with another one. 35 | * 36 | * This is primarily used internally. 37 | * 38 | * @param other the other status. 39 | * @return Status 40 | */ 41 | public Status mergeWith(final Status other) { 42 | return this.ordinal() > other.ordinal() ? this : other; 43 | } 44 | 45 | /** 46 | * {@inheritDoc} 47 | * 48 | * Returns a lower-case representation of the status. 49 | * 50 | * @return ok, deprecated or gone. 51 | */ 52 | public String toString() { 53 | return name().toLowerCase(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /jsonhome-generator/src/main/resources/jsonhome/freemarker/directresource.ftl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | json-home 8 | 9 | 10 |

${resource.linkRelationType}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | <#include "hints-rows.ftl"> 45 | 46 | 47 | 48 | 49 | 50 | 51 |
AttributeValueDescription
Rel${resource.linkRelationType} 25 | <#if resource.hints.docs.hasDescription()> 26 | <#list resource.hints.docs.description as doc> 27 |

${doc}

28 | 29 | 30 | <#if resource.hints.docs.hasDetailedDescription()> 31 | ${hrefVar.docs.detailedDescription} 32 |
33 | 34 | <#if resource.hints.docs.hasLink()> 35 |

See ${resource.hints.docs.link}

36 | 37 |
Href${resource.href}The href link to the resource.
 
52 | 53 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/converter/JsonHomeMediaType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.converter; 18 | 19 | import java.util.EnumSet; 20 | 21 | /** 22 | * @author Guido Steinacker 23 | * @since 25.11.12 24 | */ 25 | public enum JsonHomeMediaType { 26 | 27 | APPLICATION_JSON("application/json"), 28 | APPLICATION_JSONHOME("application/json-home"); 29 | 30 | public static JsonHomeMediaType mediaTypeFrom(final String value) { 31 | for (final JsonHomeMediaType mediaType : EnumSet.allOf(JsonHomeMediaType.class)) { 32 | if (mediaType.toString().equals(value)) { 33 | return mediaType; 34 | } 35 | } 36 | throw new IllegalArgumentException("Unknown media type '" + value + "'."); 37 | } 38 | 39 | private final String value; 40 | 41 | private JsonHomeMediaType(final String value) { 42 | this.value = value; 43 | } 44 | 45 | /** 46 | * Returns the value of the media type: application/json, application/json-home. 47 | * @return value 48 | */ 49 | @Override 50 | public String toString() { 51 | return value; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /jsonhome-examples/helloworld/src/main/java/de/otto/jsonhome/example/helloworld/HelloController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.example.helloworld; 17 | 18 | import de.otto.jsonhome.annotation.Doc; 19 | import de.otto.jsonhome.annotation.Rel; 20 | import org.springframework.stereotype.Controller; 21 | import org.springframework.web.bind.annotation.RequestMapping; 22 | import org.springframework.web.bind.annotation.ResponseBody; 23 | 24 | 25 | /** 26 | * Controller used to serve the hello-world resource. 27 | * 28 | * @author Guido Steinacker 29 | * @since 15.09.12 30 | */ 31 | @Controller 32 | @Rel("/rel/hello-world-example") 33 | @Doc(rel = "/rel/hello-world-example", 34 | value = "The hello-world example resource" 35 | ) 36 | public class HelloController { 37 | 38 | @RequestMapping(value = "/", produces = {"text/html", "*/*"}) 39 | @ResponseBody 40 | public String getHelloWorld() { 41 | return "

Hello World!

Open json-home

"; 42 | } 43 | 44 | @RequestMapping(value = "/", produces = "text/plain") 45 | @ResponseBody 46 | public String getHelloWorldAsPlainText() { 47 | return "Hello World!"; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/resource/JerseyJsonHomeSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.resource; 18 | 19 | import de.otto.jsonhome.generator.JsonHomeGenerator; 20 | import de.otto.jsonhome.generator.JsonHomeSource; 21 | import de.otto.jsonhome.model.JsonHome; 22 | import de.otto.jsonhome.resource.scanner.AnnotationScanner; 23 | 24 | import java.util.Collection; 25 | 26 | /** 27 | * @author Sebastian Schroeder 28 | * @since 11.12.2012 29 | */ 30 | public final class JerseyJsonHomeSource implements JsonHomeSource { 31 | 32 | private final JsonHome jsonHome; 33 | 34 | public JerseyJsonHomeSource(JsonHomeGenerator jsonHomeGenerator, AnnotationScanner annotationScanner) { 35 | jsonHome = jsonHomeGenerator.with(annotationScanner.scanClasses()).generate(); 36 | } 37 | 38 | public JerseyJsonHomeSource(JsonHomeGenerator jsonHomeGenerator, Collection> classes) { 39 | jsonHome = jsonHomeGenerator.with(classes).generate(); 40 | } 41 | 42 | /** 43 | * Returns a JsonHome instance. 44 | * 45 | * @return JsonHome. 46 | */ 47 | @Override 48 | public JsonHome getJsonHome() { 49 | return jsonHome; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /jsonhome-registry/src/test/java/de/otto/jsonhome/registry/store/LinkTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.store; 18 | 19 | import org.testng.annotations.Test; 20 | 21 | import java.net.URI; 22 | 23 | import static org.testng.Assert.assertEquals; 24 | 25 | /** 26 | * @author Guido Steinacker 27 | * @since 18.11.12 28 | */ 29 | public class LinkTest { 30 | 31 | public static final String TITLE = "foo"; 32 | public static final URI EXAMPLE_DOT_ORG = URI.create("http://example.org"); 33 | 34 | @Test() 35 | public void shouldSetTitleToEmptyStringIfTitleIsNull() { 36 | final Link link = new Link(EXAMPLE_DOT_ORG, null); 37 | assertEquals(link.getTitle(), ""); 38 | } 39 | 40 | @Test 41 | public void shouldAcceptEmptyTitle() { 42 | final Link link = new Link(EXAMPLE_DOT_ORG, ""); 43 | assertEquals(link.getTitle(), ""); 44 | } 45 | 46 | @Test(expectedExceptions = NullPointerException.class) 47 | public void shouldThrowExceptionIfHrefIsNull() { 48 | new Link(null, TITLE); 49 | } 50 | 51 | @Test(expectedExceptions = IllegalArgumentException.class) 52 | public void shouldThrowExceptionIfHrefIsNotAbsolute() { 53 | new Link(URI.create("/foo"), TITLE); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /jsonhome-spring/src/main/java/de/otto/jsonhome/generator/SpringHrefVarsGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import org.springframework.web.bind.annotation.PathVariable; 20 | import org.springframework.web.bind.annotation.RequestParam; 21 | 22 | import java.net.URI; 23 | 24 | /** 25 | * A HrefVarsGenerator used to generate HrefVars for Spring-based applications. 26 | */ 27 | public class SpringHrefVarsGenerator extends HrefVarsGenerator { 28 | 29 | /** 30 | * Creates a SpringHrefVarsGenerator. 31 | * 32 | * @param relationTypeBaseUri the base URI used to create absolute relation-type URIs. 33 | * @param docRootDir the root classpath directory containing Markdown documents. May be null. 34 | */ 35 | public SpringHrefVarsGenerator(final URI relationTypeBaseUri, final String docRootDir) { 36 | super(relationTypeBaseUri, docRootDir); 37 | } 38 | 39 | @Override 40 | protected boolean hasRequestParam(final ParameterInfo parameterInfo) { 41 | return parameterInfo.hasAnnotation(RequestParam.class); 42 | } 43 | 44 | @Override 45 | protected boolean hasPathVariable(final ParameterInfo parameterInfo) { 46 | return parameterInfo.hasAnnotation(PathVariable.class); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/annotation/HrefTemplate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.annotation; 17 | 18 | import java.lang.annotation.*; 19 | 20 | /** 21 | * Overrides the href-template and href-vars of a templated resource link. 22 | * 23 | * Use this annotation if you have to override the behaviour of the generator in use (like, for example, 24 | * the SpringJsonHomeGenerator). Use this annotation with care, because 25 | * if you are specifying the wrong URI, the href link in your json-home will be resolvable by your application. 26 | * 27 | * @author Guido Steinacker 28 | * @since 15.09.12 29 | */ 30 | @Target(ElementType.METHOD) 31 | @Retention(RetentionPolicy.RUNTIME) 32 | @Documented 33 | public @interface HrefTemplate { 34 | 35 | /** 36 | * The templated URI uniquely identifying the href-template of a linked resource. 37 | * 38 | * The href-vars are parsed from the specified template. 39 | * 40 | * Because it is not possible to associate {@link Doc documentation} with the variables used in the 41 | * href-template, you should consider adding some appropriate documentation to the resource link itself. 42 | * 43 | * @return URI of the linked resource 44 | */ 45 | String value(); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/generator/JerseyHrefVarsGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import javax.ws.rs.PathParam; 20 | import javax.ws.rs.QueryParam; 21 | import java.net.URI; 22 | 23 | /** 24 | * @author Sebastian Schroeder 25 | * @since 09.12.2012 26 | */ 27 | public final class JerseyHrefVarsGenerator extends HrefVarsGenerator { 28 | 29 | public JerseyHrefVarsGenerator(final URI relationTypeBaseUri, final String docRootDir) { 30 | super(relationTypeBaseUri, docRootDir); 31 | } 32 | 33 | /** 34 | * @param parameterInfo information about a method parameter. 35 | * @return true if the parameterInfo is describing a request parameter, false otherwise. 36 | */ 37 | @Override 38 | protected boolean hasRequestParam(ParameterInfo parameterInfo) { 39 | return parameterInfo.hasAnnotation(QueryParam.class); 40 | } 41 | 42 | /** 43 | * @param parameterInfo information about a method parameter. 44 | * @return true if the parameterInfo is describing a path variable, false otherwise. 45 | */ 46 | @Override 47 | protected boolean hasPathVariable(ParameterInfo parameterInfo) { 48 | return parameterInfo.hasAnnotation(PathParam.class); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /jsonhome-registry/src/main/java/de/otto/jsonhome/registry/store/InMemoryRegistryRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.store; 18 | 19 | import java.util.Set; 20 | import java.util.concurrent.ConcurrentHashMap; 21 | import java.util.concurrent.ConcurrentMap; 22 | 23 | /** 24 | * In-memory implementation of the {@link RegistryRepository} interface. 25 | */ 26 | public class InMemoryRegistryRepository implements RegistryRepository { 27 | 28 | public final ConcurrentMap registry = new ConcurrentHashMap<>(); 29 | 30 | /** 31 | * {@inheritDoc} 32 | */ 33 | @Override 34 | public void createOrUpdate(Registry registry) { 35 | this.registry.put(registry.getName(), registry); 36 | } 37 | 38 | /** 39 | * {@inheritDoc} 40 | */ 41 | @Override 42 | public void delete(final String name) { 43 | registry.remove(name); 44 | } 45 | 46 | /** 47 | * {@inheritDoc} 48 | */ 49 | @Override 50 | public Set getKnownNames() { 51 | return registry.keySet(); 52 | } 53 | 54 | @Override 55 | public Registry get(final String registryName) { 56 | return registry.get(registryName); 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | */ 62 | @Override 63 | public void clear() { 64 | registry.clear(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /jsonhome-registry/src/main/java/de/otto/jsonhome/registry/store/RegistryRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.store; 18 | 19 | import java.util.Set; 20 | 21 | /** 22 | * A repository used to store {@link Registry}. 23 | * 24 | * The registries are identified by their names. 25 | * 26 | * @author Guido Steinacker 27 | * @since 14.11.12 28 | */ 29 | public interface RegistryRepository { 30 | 31 | /** 32 | * Creates or updates Registry. 33 | * 34 | * An existing Registry instance with the same name as the Registry provided as parameter will be be replaced. 35 | * 36 | * @param registry the Registry instance. 37 | */ 38 | public void createOrUpdate(Registry registry); 39 | 40 | /** 41 | * Deletes a {@link Registry} instance identified by it's name. 42 | * 43 | * @param name the name of the deleted registry. 44 | */ 45 | public void delete(String name); 46 | 47 | /** 48 | * Returns the names of all known Registry instances. 49 | * 50 | * @return registry names. 51 | */ 52 | public Set getKnownNames(); 53 | 54 | /** 55 | * Returns the registry with the specifed name, or null if no such registry exists. 56 | */ 57 | public Registry get(String registryName); 58 | 59 | /** 60 | * Removes all Registry from the repository. 61 | */ 62 | void clear(); 63 | } 64 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/java/de/otto/jsonhome/resource/scanner/AnnotationScannerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.resource.scanner; 18 | 19 | import org.testng.annotations.Test; 20 | 21 | import java.util.Arrays; 22 | import java.util.Collection; 23 | import java.util.HashSet; 24 | 25 | import static org.testng.AssertJUnit.assertEquals; 26 | import static org.testng.AssertJUnit.assertTrue; 27 | 28 | public class AnnotationScannerTest { 29 | 30 | @Test 31 | public void testScanningOnePackage() throws Exception { 32 | Collection> classes = new AnnotationScanner(new HashSet( 33 | Arrays.asList("de.otto.jsonhome.fixtures.one"))).scanClasses(); 34 | assertEquals(2, classes.size()); 35 | } 36 | 37 | @Test 38 | public void testScanningTwoPackages() throws Exception { 39 | Collection> classes = new AnnotationScanner(new HashSet( 40 | Arrays. asList("de.otto.jsonhome.fixtures.one", "de.otto.jsonhome.fixtures.two"))).scanClasses(); 41 | assertEquals(4, classes.size()); 42 | } 43 | 44 | @Test 45 | public void testScanningNotExistingPackage() throws Exception { 46 | Collection> classes = new AnnotationScanner(new HashSet( 47 | Arrays. asList("de.otto.jsonhome.fixtures.none"))).scanClasses(); 48 | assertTrue(classes.isEmpty()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /jsonhome-spring/src/test/java/de/otto/jsonhome/controller/DocControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.controller; 18 | 19 | import org.springframework.core.io.ClassPathResource; 20 | import org.springframework.mock.web.MockHttpServletRequest; 21 | import org.testng.annotations.Test; 22 | 23 | import java.io.IOException; 24 | 25 | import static org.testng.Assert.assertTrue; 26 | 27 | /** 28 | * @author Guido Steinacker 29 | * @since 17.02.13 30 | */ 31 | public class DocControllerTest { 32 | 33 | @Test 34 | public void shouldReturnMarkdown() throws IOException { 35 | // given 36 | final DocController controller = new DocController(); 37 | controller.setRootDir(new ClassPathResource("/test/**")); 38 | // when 39 | final String markdown = controller.getMarkdown( 40 | new MockHttpServletRequest("GET", "/test/doc/test.md")); 41 | // then 42 | assertTrue(markdown.startsWith("Test")); 43 | } 44 | 45 | @Test 46 | public void shouldReturnMarkdownAsHtml() throws IOException { 47 | // given 48 | final DocController controller = new DocController(); 49 | controller.setRootDir(new ClassPathResource("/test/**")); 50 | // when 51 | final String markdown = controller.getMarkdownAsHtml( 52 | new MockHttpServletRequest("GET", "/test/doc/test.md")); 53 | // then 54 | assertTrue(markdown.startsWith("

Test

")); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /jsonhome-generator/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | dependencies { 3 | compile project(':jsonhome-core') 4 | compile 'org.markdown:markdown4j:2.2' 5 | compile 'org.springframework:spring-core:4.1.7.RELEASE' 6 | testCompile 'org.testng:testng:6.9.6' 7 | } 8 | 9 | artifacts { 10 | archives jar 11 | archives javadocJar 12 | archives sourcesJar 13 | } 14 | 15 | signing { 16 | sign configurations.archives 17 | } 18 | 19 | uploadArchives { 20 | repositories { 21 | mavenDeployer { 22 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 23 | 24 | repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { 25 | authentication(userName: sonatypeUsername, password: sonatypePassword) 26 | } 27 | snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { 28 | authentication(userName: sonatypeUsername, password: sonatypePassword) 29 | } 30 | pom.project { 31 | name 'jsonhome-generator' 32 | packaging 'jar' 33 | description 'Generator library of the jsonhome project.' 34 | url 'http://github.com/otto-de/jsonhome' 35 | 36 | scm { 37 | url 'scm:git@github.com:otto-de/jsonhome.git' 38 | connection 'scm:git@github.com:otto-de/jsonhome.git' 39 | developerConnection 'scm:git@github.com:otto-de/jsonhome.git' 40 | } 41 | 42 | licenses { 43 | license { 44 | name 'The Apache Software License, Version 2.0' 45 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 46 | distribution 'repo' 47 | } 48 | } 49 | 50 | developers { 51 | developer { 52 | id 'gsteinacker' 53 | name 'Guido Steinacker' 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/model/JsonHomeBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.model; 17 | 18 | import java.net.URI; 19 | import java.util.Collection; 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | 23 | /** 24 | * A builder used to build JsonHome instances. 25 | */ 26 | public final class JsonHomeBuilder { 27 | 28 | private final Map resources = new HashMap(); 29 | 30 | private JsonHomeBuilder() { 31 | } 32 | 33 | public static JsonHomeBuilder jsonHomeBuilder() { 34 | return new JsonHomeBuilder(); 35 | } 36 | 37 | public static JsonHomeBuilder copyFrom(final JsonHome jsonHome) { 38 | return jsonHomeBuilder().mergeWith(jsonHome); 39 | } 40 | 41 | public JsonHomeBuilder mergeWith(final JsonHome jsonHome) { 42 | resources.putAll(jsonHome.getResources()); 43 | return this; 44 | } 45 | 46 | public JsonHomeBuilder addResource(final ResourceLink resource) { 47 | this.resources.put(resource.getLinkRelationType(), resource); 48 | return this; 49 | } 50 | 51 | public JsonHomeBuilder addResources(final Collection resources) { 52 | for (final ResourceLink resource : resources) { 53 | this.resources.put(resource.getLinkRelationType(), resource); 54 | } 55 | return this; 56 | } 57 | 58 | public JsonHome build() { 59 | return JsonHome.jsonHome(resources.values()); 60 | } 61 | } -------------------------------------------------------------------------------- /jsonhome-client/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | dependencies { 3 | compile project(':jsonhome-core') 4 | compile 'org.apache.httpcomponents:httpclient:4.5' 5 | compile 'org.apache.httpcomponents:httpclient-cache:4.5' 6 | testCompile 'org.testng:testng:6.9.6' 7 | } 8 | 9 | artifacts { 10 | archives jar 11 | archives javadocJar 12 | archives sourcesJar 13 | } 14 | 15 | signing { 16 | sign configurations.archives 17 | } 18 | 19 | uploadArchives { 20 | repositories { 21 | mavenDeployer { 22 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 23 | 24 | repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { 25 | authentication(userName: sonatypeUsername, password: sonatypePassword) 26 | } 27 | snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { 28 | authentication(userName: sonatypeUsername, password: sonatypePassword) 29 | } 30 | pom.project { 31 | name 'jsonhome-client' 32 | packaging 'jar' 33 | description 'Generator library of the jsonhome project.' 34 | url 'http://github.com/otto-de/jsonhome' 35 | 36 | scm { 37 | url 'scm:git@github.com:otto-de/jsonhome.git' 38 | connection 'scm:git@github.com:otto-de/jsonhome.git' 39 | developerConnection 'scm:git@github.com:otto-de/jsonhome.git' 40 | } 41 | 42 | licenses { 43 | license { 44 | name 'The Apache Software License, Version 2.0' 45 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 46 | distribution 'repo' 47 | } 48 | } 49 | 50 | developers { 51 | developer { 52 | id 'gsteinacker' 53 | name 'Guido Steinacker' 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /jsonhome-registry/src/test/java/de/otto/jsonhome/registry/controller/RegistryConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.controller; 18 | 19 | import de.otto.jsonhome.registry.store.Registry; 20 | import org.testng.annotations.Test; 21 | 22 | import java.util.Map; 23 | 24 | import static de.otto.jsonhome.registry.controller.RegistryConverter.jsonToRegistry; 25 | import static de.otto.jsonhome.registry.controller.RegistryConverter.registryToJson; 26 | import static de.otto.jsonhome.registry.fixture.RegistryFixture.doubleEntryRegistry; 27 | import static de.otto.jsonhome.registry.fixture.RegistryFixture.registryLiveWithSingleLinkTo; 28 | import static java.net.URI.create; 29 | import static org.testng.Assert.assertEquals; 30 | 31 | /** 32 | * @author Guido Steinacker 33 | * @since 09.02.13 34 | */ 35 | public class RegistryConverterTest { 36 | 37 | @Test 38 | public void shouldConvertRegistryWithSingleEntry() { 39 | // given: 40 | final Map linksMap = registryLiveWithSingleLinkTo("foo"); 41 | // when: 42 | final Registry registry = jsonToRegistry(linksMap); 43 | // then: 44 | assertEquals(registryToJson(create("http://example.org"), registry), linksMap); 45 | } 46 | 47 | @Test 48 | public void shouldConvertRegistryWithMultipleEntries() { 49 | // given: 50 | final Map linksMap = doubleEntryRegistry(); 51 | // when: 52 | final Registry registry = jsonToRegistry(linksMap); 53 | // then: 54 | assertEquals(registryToJson(create("http://example.org"), registry), linksMap); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /jsonhome-registry/src/main/java/de/otto/jsonhome/registry/controller/LinkConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.controller; 18 | 19 | import de.otto.jsonhome.registry.store.Link; 20 | 21 | import java.util.Collection; 22 | import java.util.LinkedHashMap; 23 | import java.util.List; 24 | import java.util.Map; 25 | 26 | import static java.net.URI.create; 27 | import static java.util.stream.Collectors.toList; 28 | 29 | /** 30 | * @author Guido Steinacker 31 | * @since 11.02.13 32 | */ 33 | public class LinkConverter { 34 | 35 | private LinkConverter() {} 36 | 37 | public static Map linkToJson(final Link link) { 38 | final Map json = new LinkedHashMap<>(); 39 | json.put("href", link.getHref().toString()); 40 | if (!link.getTitle().isEmpty()) { 41 | json.put("title", link.getTitle()); 42 | } 43 | return json; 44 | } 45 | 46 | public static Link jsonToLink(final Map json) { 47 | return new Link( 48 | create(json.get("href")), 49 | json.get("title") 50 | ); 51 | } 52 | 53 | public static List> linksToJson(final Collection links) { 54 | return links 55 | .stream() 56 | .map(LinkConverter::linkToJson) 57 | .collect(toList()); 58 | } 59 | 60 | public static List jsonToLinks(final Collection> json) { 61 | return json 62 | .stream() 63 | .map(LinkConverter::jsonToLink) 64 | .collect(toList()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /jsonhome-registry/src/test/resources/testSpringContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | http://specs.example.org 14 | http://example.org 15 | default 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 28 | 31 | 32 | 35 | 38 | 39 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /jsonhome-spring/src/test/java/de/otto/jsonhome/controller/GeneratorBasedJsonHomeSourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.controller; 18 | 19 | import de.otto.jsonhome.generator.JsonHomeGenerator; 20 | import de.otto.jsonhome.generator.JsonHomeSource; 21 | import de.otto.jsonhome.generator.SpringJsonHomeGenerator; 22 | import de.otto.jsonhome.model.JsonHome; 23 | import org.testng.annotations.Test; 24 | 25 | import static de.otto.jsonhome.fixtures.ControllerFixtures.ControllerWithoutResource; 26 | import static org.testng.Assert.assertNotNull; 27 | 28 | /** 29 | * @author Guido Steinacker 30 | * @since 06.10.12 31 | */ 32 | public class GeneratorBasedJsonHomeSourceTest { 33 | 34 | @Test 35 | public void shouldReturnJsonHomeInstance() { 36 | // given 37 | final JsonHomeSource jsonHomeControllerBase = getJsonHomeSource(); 38 | // when 39 | final JsonHome jsonHome = jsonHomeControllerBase.getJsonHome(); 40 | // then 41 | assertNotNull(jsonHome); 42 | } 43 | 44 | private JsonHomeSource getJsonHomeSource() { 45 | final GeneratorBasedJsonHomeSource source = new GeneratorBasedJsonHomeSource(); 46 | source.setControllerTypes(ControllerWithoutResource.class); 47 | source.setJsonHomeGenerator(getJsonHomeGenerator()); 48 | return source; 49 | } 50 | 51 | private JsonHomeGenerator getJsonHomeGenerator() { 52 | final SpringJsonHomeGenerator jsonHomeGenerator = new SpringJsonHomeGenerator(); 53 | jsonHomeGenerator.setApplicationBaseUri("http://app.example.org/"); 54 | jsonHomeGenerator.setRelationTypeBaseUri("http://rel.example.org/"); 55 | jsonHomeGenerator.postConstruct(); 56 | return jsonHomeGenerator; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /jsonhome-core/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | dependencies { 3 | // uri-template library: 4 | compile 'com.damnhandy:handy-uri-templates:2.0.2' 5 | // jackson json mapper: 6 | compile 'org.codehaus.jackson:jackson-core-asl:1.9.13' 7 | compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13' 8 | // logging: 9 | compile 'org.slf4j:slf4j-api:1.7.12' 10 | testCompile 'ch.qos.logback:logback-core:1.1.3' 11 | testCompile 'ch.qos.logback:logback-classic:1.1.3' 12 | // testng: 13 | testCompile 'org.testng:testng:6.9.6' 14 | } 15 | 16 | artifacts { 17 | archives jar 18 | archives javadocJar 19 | archives sourcesJar 20 | } 21 | 22 | signing { 23 | sign configurations.archives 24 | } 25 | 26 | uploadArchives { 27 | repositories { 28 | mavenDeployer { 29 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 30 | 31 | repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { 32 | authentication(userName: sonatypeUsername, password: sonatypePassword) 33 | } 34 | snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { 35 | authentication(userName: sonatypeUsername, password: sonatypePassword) 36 | } 37 | 38 | pom.project { 39 | name 'jsonhome-core' 40 | packaging 'jar' 41 | description 'Core library of the jsonhome project.' 42 | url 'http://github.com/otto-de/jsonhome' 43 | 44 | scm { 45 | url 'scm:git@github.com:otto-de/jsonhome.git' 46 | connection 'scm:git@github.com:otto-de/jsonhome.git' 47 | developerConnection 'scm:git@github.com:otto-de/jsonhome.git' 48 | } 49 | 50 | licenses { 51 | license { 52 | name 'The Apache Software License, Version 2.0' 53 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 54 | distribution 'repo' 55 | } 56 | } 57 | 58 | developers { 59 | developer { 60 | id 'gsteinacker' 61 | name 'Guido Steinacker' 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /jsonhome-registry/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile 'org.springframework:spring-webmvc:4.1.7.RELEASE' 3 | compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13' 4 | compile 'org.freemarker:freemarker:2.3.23' 5 | compile project(':jsonhome-core') 6 | compile project(':jsonhome-generator') 7 | compile project(':jsonhome-spring') 8 | compile project(':jsonhome-client') 9 | testCompile 'org.testng:testng:6.9.6' 10 | testCompile 'org.springframework:spring-test:4.1.7.RELEASE' 11 | } 12 | 13 | artifacts { 14 | archives jar 15 | archives javadocJar 16 | archives sourcesJar 17 | } 18 | 19 | signing { 20 | sign configurations.archives 21 | } 22 | 23 | uploadArchives { 24 | repositories { 25 | mavenDeployer { 26 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 27 | 28 | repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { 29 | authentication(userName: sonatypeUsername, password: sonatypePassword) 30 | } 31 | snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { 32 | authentication(userName: sonatypeUsername, password: sonatypePassword) 33 | } 34 | pom.project { 35 | name 'jsonhome-registry' 36 | packaging 'jar' 37 | description 'Library used to write json-home registries for multiple json-home sources.' 38 | url 'http://github.com/otto-de/jsonhome' 39 | 40 | scm { 41 | url 'scm:git@github.com:otto-de/jsonhome.git' 42 | connection 'scm:git@github.com:otto-de/jsonhome.git' 43 | developerConnection 'scm:git@github.com:otto-de/jsonhome.git' 44 | } 45 | 46 | licenses { 47 | license { 48 | name 'The Apache Software License, Version 2.0' 49 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 50 | distribution 'repo' 51 | } 52 | } 53 | 54 | developers { 55 | developer { 56 | id 'gsteinacker' 57 | name 'Guido Steinacker' 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /jsonhome-jersey/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | dependencies { 3 | compile project(':jsonhome-core') 4 | compile project(':jsonhome-generator') 5 | compile 'com.sun.jersey:jersey-core:1.19' 6 | compile 'com.sun.jersey:jersey-json:1.19' 7 | compile 'com.sun.jersey:jersey-server:1.19' 8 | compile 'org.reflections:reflections:0.9.10' 9 | testCompile 'org.testng:testng:6.9.6' 10 | } 11 | 12 | artifacts { 13 | archives jar 14 | archives javadocJar 15 | archives sourcesJar 16 | } 17 | 18 | signing { 19 | sign configurations.archives 20 | } 21 | 22 | uploadArchives { 23 | repositories { 24 | mavenDeployer { 25 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 26 | 27 | repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { 28 | authentication(userName: sonatypeUsername, password: sonatypePassword) 29 | } 30 | snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { 31 | authentication(userName: sonatypeUsername, password: sonatypePassword) 32 | } 33 | 34 | pom.project { 35 | name 'jsonhome-jersey' 36 | packaging 'jar' 37 | description 'Jersey library of the jsonhome project.' 38 | url 'http://github.com/otto-de/jsonhome' 39 | 40 | scm { 41 | url 'scm:git@github.com:otto-de/jsonhome.git' 42 | connection 'scm:git@github.com:otto-de/jsonhome.git' 43 | developerConnection 'scm:git@github.com:otto-de/jsonhome.git' 44 | } 45 | 46 | licenses { 47 | license { 48 | name 'The Apache Software License, Version 2.0' 49 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 50 | distribution 'repo' 51 | } 52 | } 53 | 54 | developers { 55 | developer { 56 | id 'gsteinacker' 57 | name 'Guido Steinacker' 58 | } 59 | developer { 60 | id 'SebastianSchroeder' 61 | name 'Sebastian Schroeder' 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /jsonhome-generator/src/main/java/de/otto/jsonhome/generator/UriTemplateHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.generator; 17 | 18 | import java.io.Serializable; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.regex.Matcher; 22 | import java.util.regex.Pattern; 23 | 24 | /** 25 | * Represents a URI template. A URI template is a URI-like String that contains variables enclosed 26 | * by braces ({, }), which can be expanded to produce an actual URI. 27 | * 28 | * @see URI Templates 29 | */ 30 | public class UriTemplateHelper implements Serializable { 31 | 32 | /** Captures URI template variable names. */ 33 | private static final Pattern NAMES_PATTERN = Pattern.compile("\\{[\\/+#;\\.\\?&]?([^/]+?)[\\*]?\\}"); 34 | 35 | public static List variableNamesFrom(final String uriTemplate) { 36 | final List variableNames = new ArrayList<>(); 37 | Matcher m = NAMES_PATTERN.matcher(uriTemplate); 38 | while (m.find()) { 39 | String match = m.group(1); 40 | String[] parts = match.split(","); 41 | for (final String part : parts) { 42 | int colonIdx = part.indexOf(':'); 43 | if (colonIdx == -1) { 44 | variableNames.add(part); 45 | } 46 | else { 47 | if (colonIdx + 1 == part.length()) { 48 | throw new IllegalArgumentException("No custom regular expression specified after ':' in \"" + part + "\""); 49 | } 50 | variableNames.add(part.substring(0, colonIdx)); 51 | } 52 | } 53 | } 54 | return variableNames; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /jsonhome-examples/hellojersey/src/main/resources/freemarker/jsonhome/templatedresource.ftl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | json-home 7 | 8 | 9 |

${resource.linkRelationType}

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 64 | 65 | <#include "hints-rows.ftl"/> 66 | 67 | 68 | 69 | 70 | 71 | 72 |
AttributeValueDescription
Rel${resource.linkRelationType} 24 | <#list resource.hints.docs.description as descr> 25 | ${descr}
26 | 27 | <#if resource.hints.docs.link?has_content> 28 | See ${resource.hints.docs.link} 29 | 30 |
Href-template${resource.hrefTemplate}The href-template used to build links to the resource.
Href-vars 40 | 41 | 42 | 43 | 44 | 45 | 46 | <#list resource.hrefVars as hrefVar> 47 | 48 | 49 | 50 | 60 | 61 | 62 |
VariableTypeDescription
${hrefVar.var}${hrefVar.varType} 51 | <#if hrefVar.docs.hasDescription()> 52 | <#list hrefVar.docs.description as descr> 53 | ${descr}
54 | 55 | 56 | <#if hrefVar.docs.hasLink()> 57 | See ${hrefVar.docs.link} 58 | 59 |
63 |
 
73 | 74 | -------------------------------------------------------------------------------- /jsonhome-spring/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile project(':jsonhome-core') 3 | compile project(':jsonhome-generator') 4 | compile 'org.freemarker:freemarker:2.3.23' 5 | compile 'org.springframework:spring-webmvc:4.1.7.RELEASE' 6 | compile 'cglib:cglib-nodep:3.1' 7 | compile 'javax.servlet:javax.servlet-api:3.1.0' 8 | testCompile 'org.testng:testng:6.9.6' 9 | testCompile 'org.springframework:spring-test:4.1.7.RELEASE' 10 | testCompile 'org.springframework:spring-aop:4.1.7.RELEASE' 11 | testCompile "org.aspectj:aspectjrt:1.8.6" 12 | testCompile "org.aspectj:aspectjweaver:1.8.6" 13 | 14 | } 15 | 16 | artifacts { 17 | archives jar 18 | archives javadocJar 19 | archives sourcesJar 20 | } 21 | 22 | signing { 23 | sign configurations.archives 24 | } 25 | 26 | uploadArchives { 27 | repositories { 28 | mavenDeployer { 29 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 30 | 31 | repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { 32 | authentication(userName: sonatypeUsername, password: sonatypePassword) 33 | } 34 | snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { 35 | authentication(userName: sonatypeUsername, password: sonatypePassword) 36 | } 37 | 38 | pom.project { 39 | name 'jsonhome-spring' 40 | packaging 'jar' 41 | description 'Spring library of the jsonhome project.' 42 | url 'http://github.com/otto-de/jsonhome' 43 | 44 | scm { 45 | url 'scm:git@github.com:otto-de/jsonhome.git' 46 | connection 'scm:git@github.com:otto-de/jsonhome.git' 47 | developerConnection 'scm:git@github.com:otto-de/jsonhome.git' 48 | } 49 | 50 | licenses { 51 | license { 52 | name 'The Apache Software License, Version 2.0' 53 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 54 | distribution 'repo' 55 | } 56 | } 57 | 58 | developers { 59 | developer { 60 | id 'gsteinacker' 61 | name 'Guido Steinacker' 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /jsonhome-client/src/test/java/de/otto/jsonhome/client/SimpleJsonHomeClientTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.client; 18 | 19 | import de.otto.jsonhome.model.JsonHome; 20 | import org.testng.annotations.Test; 21 | 22 | import java.net.URI; 23 | 24 | import static de.otto.jsonhome.model.DirectLink.directLink; 25 | import static de.otto.jsonhome.model.JsonHome.jsonHome; 26 | import static java.net.URI.create; 27 | import static java.util.Arrays.asList; 28 | import static org.testng.Assert.assertNotNull; 29 | import static org.testng.Assert.assertTrue; 30 | 31 | /** 32 | * @author Guido Steinacker 33 | * @since 26.10.12 34 | */ 35 | public class SimpleJsonHomeClientTest { 36 | 37 | public static final URI RELATION_TYPE_URI = create("http://example.org/rel/widgets"); 38 | public static final URI JSONHOME_URI = create("http://example.org/json-home"); 39 | public static final JsonHome JSON_HOME = jsonHome(asList( 40 | directLink(RELATION_TYPE_URI, create("http://example.org/widgets"), null)) 41 | ); 42 | 43 | @Test 44 | public void shouldFindRegisteredResource() { 45 | // given 46 | final SimpleJsonHomeClient simpleJsonHomeClient = new SimpleJsonHomeClient(); 47 | simpleJsonHomeClient.register(JSONHOME_URI, JSON_HOME); 48 | // when 49 | final JsonHome jsonHome = simpleJsonHomeClient.get(JSONHOME_URI); 50 | // then 51 | assertNotNull(jsonHome); 52 | assertTrue(jsonHome.hasResourceFor(RELATION_TYPE_URI)); 53 | } 54 | 55 | @Test(expectedExceptions = NotFoundException.class) 56 | public void shouldReturnNullForUnregisteredResource() { 57 | // given 58 | final SimpleJsonHomeClient simpleJsonHomeClient = new SimpleJsonHomeClient(); 59 | // when 60 | simpleJsonHomeClient.get(JSONHOME_URI); 61 | // then an exception is thrown 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/generator/JerseyHintsGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import de.otto.jsonhome.model.Allow; 20 | 21 | import javax.ws.rs.Consumes; 22 | import javax.ws.rs.Produces; 23 | import java.lang.annotation.Annotation; 24 | import java.lang.reflect.Method; 25 | import java.net.URI; 26 | import java.util.*; 27 | 28 | /** 29 | * @author Sebastian Schroeder 30 | * @since 09.12.2012 31 | */ 32 | public final class JerseyHintsGenerator extends HintsGenerator { 33 | 34 | public JerseyHintsGenerator(final URI relationTypeBaseUri, final String docRootDir) { 35 | super(relationTypeBaseUri, docRootDir); 36 | } 37 | 38 | @Override 39 | protected Set allowedHttpMethodsOf(final Method method) { 40 | final Annotation[] annotations = method.getDeclaredAnnotations(); 41 | final Set allows = EnumSet.noneOf(Allow.class); 42 | for (final Annotation annotation : annotations) { 43 | if (HttpMethods.isHttpMethod(annotation)) { 44 | allows.add(Allow.valueOf(annotation.annotationType().getSimpleName())); 45 | } 46 | } 47 | return allows; 48 | } 49 | 50 | @Override 51 | protected List producedRepresentationsOf(final Method method) { 52 | final Produces produces = method.getAnnotation(Produces.class); 53 | return produces == null 54 | ? Collections.emptyList() 55 | : Arrays.asList(produces.value()); 56 | } 57 | 58 | @Override 59 | protected List consumedRepresentationsOf(final Method method) { 60 | final Consumes consumes = method.getAnnotation(Consumes.class); 61 | return consumes == null 62 | ? Collections.emptyList() 63 | : Arrays.asList(consumes.value()); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /jsonhome-generator/src/test/java/de/otto/jsonhome/generator/UriTemplateHelperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import org.testng.annotations.Test; 20 | 21 | import static de.otto.jsonhome.generator.UriTemplateHelper.variableNamesFrom; 22 | import static java.util.Arrays.asList; 23 | import static org.testng.Assert.assertEquals; 24 | 25 | /** 26 | * @author Guido Steinacker 27 | * @since 21.10.12 28 | */ 29 | public class UriTemplateHelperTest { 30 | 31 | @Test 32 | public void testVariableNamesFrom() { 33 | assertEquals(variableNamesFrom("http://example.org/foo{count}"), asList("count")); 34 | assertEquals(variableNamesFrom("http://example.org/foo{+count}"), asList("count")); 35 | assertEquals(variableNamesFrom("http://example.org/foo{#count}"), asList("count")); 36 | assertEquals(variableNamesFrom("http://example.org/foo{.count}"), asList("count")); 37 | assertEquals(variableNamesFrom("http://example.org/foo{count,foo}"), asList("count", "foo")); 38 | assertEquals(variableNamesFrom("http://example.org/foo{count:3}"), asList("count")); 39 | assertEquals(variableNamesFrom("http://example.org/foo{count*}"), asList("count")); 40 | assertEquals(variableNamesFrom("http://example.org/foo{/count}"), asList("count")); 41 | assertEquals(variableNamesFrom("http://example.org/foo{/count*}"), asList("count")); 42 | assertEquals(variableNamesFrom("http://example.org/foo{;count}"), asList("count")); 43 | assertEquals(variableNamesFrom("http://example.org/foo{;count*}"), asList("count")); 44 | assertEquals(variableNamesFrom("http://example.org/foo{?count}"), asList("count")); 45 | assertEquals(variableNamesFrom("http://example.org/foo{?count*}"), asList("count")); 46 | assertEquals(variableNamesFrom("http://example.org/foo{&count*}"), asList("count")); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /jsonhome-registry/src/main/java/de/otto/jsonhome/registry/controller/RegistriesConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.controller; 18 | 19 | import de.otto.jsonhome.registry.store.Link; 20 | import de.otto.jsonhome.registry.store.RegistryRepository; 21 | 22 | import java.net.URI; 23 | import java.util.ArrayList; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | 28 | import static de.otto.jsonhome.registry.controller.LinkConverter.linksToJson; 29 | import static java.util.Collections.sort; 30 | 31 | /** 32 | * Converter used to convert the registries resource documents. 33 | * 34 | * @author Guido Steinacker 35 | * @since 10.02.13 36 | */ 37 | public class RegistriesConverter { 38 | 39 | private RegistriesConverter() {} 40 | 41 | public static Map registriesToJson(final URI baseUri, final RegistryRepository repository) { 42 | final Map json = new HashMap<>(); 43 | json.put("self", baseUri + "/registries"); 44 | json.put("registries", linksToJson( 45 | repositoryLinks(baseUri, repository)) 46 | ); 47 | return json; 48 | } 49 | 50 | private static List repositoryLinks(final URI baseUri, final RegistryRepository repository) { 51 | final List registries = new ArrayList<>(); 52 | for (final String registryName : sortedNamesFrom(repository)) { 53 | registries.add(repository 54 | .get(registryName) 55 | .asLinkFor(baseUri) 56 | ); 57 | } 58 | return registries; 59 | } 60 | 61 | private static List sortedNamesFrom(final RegistryRepository repository) { 62 | final List registryNames = new ArrayList<>(repository.getKnownNames()); 63 | sort(registryNames); 64 | return registryNames; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/java/de/otto/jsonhome/example/products/ProductService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.example.products; 17 | 18 | import org.springframework.stereotype.Service; 19 | 20 | import java.util.ArrayList; 21 | import java.util.ConcurrentModificationException; 22 | import java.util.List; 23 | import java.util.concurrent.ConcurrentHashMap; 24 | import java.util.concurrent.ConcurrentMap; 25 | import java.util.concurrent.atomic.AtomicLong; 26 | 27 | /** 28 | * A service used to access and modify the products offered by the example web-shop. 29 | * 30 | * @author Guido Steinacker 31 | * @since 29.09.12 32 | */ 33 | @Service 34 | public final class ProductService { 35 | 36 | private static final AtomicLong nextId = new AtomicLong(0); 37 | private static final ConcurrentMap PRODUCTS = new ConcurrentHashMap(); 38 | static { 39 | Product p = new Product(nextId.incrementAndGet(), "Notebook", "999"); 40 | PRODUCTS.put(p.getId(), p); 41 | p = new Product(nextId.incrementAndGet(), "PC", "897"); 42 | PRODUCTS.put(p.getId(), p); 43 | } 44 | 45 | public long addProduct(final String title, final String price) { 46 | final long id = nextId.incrementAndGet(); 47 | PRODUCTS.put(id, new Product(id, title, price)); 48 | return id; 49 | } 50 | 51 | public List findProducts(final String query) { 52 | return new ArrayList(PRODUCTS.values()); 53 | } 54 | 55 | public Product findProduct(final long id) { 56 | return PRODUCTS.get(id); 57 | } 58 | 59 | public Product createOrUpdateProduct(final Product product, final Product expected) { 60 | final boolean replaced = PRODUCTS.replace(product.getId(), expected, product); 61 | if (replaced) { 62 | return expected; 63 | } else { 64 | throw new ConcurrentModificationException("Product was concurrently modified"); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/resource/scanner/AnnotationScanner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.resource.scanner; 18 | 19 | import de.otto.jsonhome.JsonHomeProperties; 20 | import org.reflections.Reflections; 21 | import org.reflections.scanners.SubTypesScanner; 22 | import org.reflections.scanners.TypeAnnotationsScanner; 23 | import org.reflections.util.ConfigurationBuilder; 24 | import org.reflections.util.FilterBuilder; 25 | 26 | import javax.ws.rs.Path; 27 | import java.util.Arrays; 28 | import java.util.HashSet; 29 | import java.util.Set; 30 | 31 | import static org.reflections.util.ClasspathHelper.forClass; 32 | import static org.reflections.util.ClasspathHelper.forPackage; 33 | 34 | /** 35 | * @author Sebastian Schroeder 36 | * @since 15.12.2012 37 | */ 38 | public final class AnnotationScanner { 39 | 40 | private final Set packages; 41 | 42 | public AnnotationScanner() { 43 | final String packages = JsonHomeProperties.getProperties().getProperty("resource.packages"); 44 | if (packages == null) { 45 | throw new IllegalStateException("resource.packages property not set in jsonhome.properties"); 46 | } 47 | this.packages = new HashSet(Arrays.asList(packages.split("\\s*,\\s*"))); 48 | } 49 | 50 | public AnnotationScanner(Set packages) { 51 | this.packages = packages; 52 | } 53 | 54 | public Set> scanClasses() { 55 | final Set> classes = new HashSet>(); 56 | for (String pkg : packages) { 57 | final Reflections reflections = new Reflections(new ConfigurationBuilder() 58 | .addUrls(forClass(Path.class)) 59 | .addUrls(forPackage(pkg)) 60 | .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner()) 61 | .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(pkg)))); 62 | classes.addAll(reflections.getTypesAnnotatedWith(Path.class)); 63 | } 64 | return classes; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/annotation/Doc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.annotation; 17 | 18 | import java.lang.annotation.Retention; 19 | import java.lang.annotation.RetentionPolicy; 20 | import java.lang.annotation.Target; 21 | 22 | import static java.lang.annotation.ElementType.PARAMETER; 23 | import static java.lang.annotation.ElementType.TYPE; 24 | 25 | /** 26 | * Documentation of a link-relation type (@Rel) or a variable used in an uri-template. 27 | * 28 | * Link-relation types must be documented at class-level and must specify the documented 29 | * type using the {@link #rel()} attribute. 30 | * 31 | * If you want to document more than one link-relation type in a single controller, you must 32 | * use the {@link Docs} annotation to add multiple Doc instances to the class. 33 | * 34 | * In case of documenting a href-template variable, the {@code rel} attribute is ignored. 35 | * 36 | * @author Guido Steinacker 37 | * @since 15.09.12 38 | */ 39 | @Target({TYPE, PARAMETER}) 40 | @Retention(RetentionPolicy.RUNTIME) 41 | public @interface Doc { 42 | 43 | /** 44 | * Optional value, consisting of one or more paragraphs. 45 | * 46 | * @return documentation 47 | */ 48 | String[] value() default ""; 49 | 50 | /** 51 | * Optional relative URI pointing to a Markdown document to include into the 52 | * HTML description of the documentation. 53 | * 54 | * @return documentation to include 55 | */ 56 | String include() default ""; 57 | 58 | /** 59 | * Optional fully qualified URI pointing to external documentation. 60 | * 61 | * @return link to documentation 62 | */ 63 | String link() default ""; 64 | 65 | /** 66 | * The URI uniquely identifying the link relation type. 67 | * 68 | * If this is a documentation of a link-relation type, this attribute must be provided. Otherwise, the 69 | * documentation can not be attached to the proper link-relation type. 70 | * 71 | * @return URI of the link relation type 72 | */ 73 | String rel() default ""; 74 | 75 | } 76 | -------------------------------------------------------------------------------- /jsonhome-spring/src/main/resources/spring/jsonhome-controller-beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | application/json-home 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 37 | 38 | 41 | 43 | 44 | 47 | 48 | 49 | 53 | 54 | 55 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /jsonhome-generator/src/main/java/de/otto/jsonhome/generator/UriBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import java.net.URI; 20 | 21 | import static java.net.URI.create; 22 | 23 | /** 24 | * A build used to build normalized URIs in jsonhome. 25 | * 26 | * @author Guido Steinacker 27 | * @since 30.03.13 28 | */ 29 | public final class UriBuilder { 30 | 31 | private final StringBuilder uri; 32 | 33 | private UriBuilder(final URI baseUri) { 34 | this.uri = new StringBuilder(withoutTrailingSlash(baseUri.toString())); 35 | } 36 | 37 | public static UriBuilder normalized(final URI baseUri) { 38 | if (baseUri == null || !baseUri.isAbsolute()) { 39 | throw new IllegalArgumentException("baseUri must be an absolute URI."); 40 | } 41 | return new UriBuilder(baseUri); 42 | } 43 | 44 | public static UriBuilder normalized(final String baseUri) { 45 | return normalized(create(baseUri)); 46 | } 47 | 48 | public UriBuilder withPathSegment(final String segment) { 49 | if (segment != null && !segment.isEmpty()) { 50 | uri.append(withLeadingSlash(withoutTrailingSlash(segment))); 51 | } 52 | return this; 53 | } 54 | 55 | public UriBuilder withPathSegments(final String... pathSegments) { 56 | for (final String pathSegment : pathSegments) { 57 | withPathSegment(pathSegment); 58 | } 59 | return this; 60 | } 61 | 62 | public URI toUri() { 63 | return create(uri.toString()); 64 | } 65 | 66 | public String toString() { 67 | return uri.toString(); 68 | } 69 | 70 | private static String withoutTrailingSlash(final String uri) { 71 | if (uri.endsWith("/")) { 72 | return uri.substring(0, uri.length() - 1); 73 | } else { 74 | return uri; 75 | } 76 | } 77 | 78 | private static String withLeadingSlash(final String uri) { 79 | if (uri.startsWith("/")) { 80 | return uri; 81 | } else { 82 | return "/" + uri; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /jsonhome-spring/src/test/java/de/otto/jsonhome/spring/SpringControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.spring; 18 | 19 | import de.otto.jsonhome.controller.JsonHomeController; 20 | import de.otto.jsonhome.fixtures.spring.TestController; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.mock.web.MockHttpServletResponse; 23 | import org.springframework.test.context.ContextConfiguration; 24 | import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; 25 | import org.testng.annotations.Test; 26 | 27 | import java.util.Map; 28 | 29 | import static org.testng.Assert.assertEquals; 30 | import static org.testng.Assert.assertNotNull; 31 | 32 | /** 33 | * @author Guido Steinacker 34 | * @since 18.12.12 35 | */ 36 | @ContextConfiguration(locations = "classpath:/testSpringContext.xml") 37 | public class SpringControllerTest extends AbstractTestNGSpringContextTests { 38 | 39 | @Autowired 40 | private TestController controller; 41 | 42 | @Autowired 43 | private JsonHomeController jsonHomeController; 44 | 45 | @Test 46 | public void controllerUsedForTestShouldExistAndWork() throws Exception { 47 | assertEquals(controller.getAFoo("42"), "42"); 48 | } 49 | 50 | @Test 51 | @SuppressWarnings("unchecked") 52 | public void shouldFindJsonHomeWithAspects() { 53 | final MockHttpServletResponse response = new MockHttpServletResponse(); 54 | final Map json = jsonHomeController.getAsApplicationJson(response); 55 | final Map> resources = (Map>) json.get("resources"); 56 | assertNotNull(resources); 57 | final Map fooResource = resources.get("http://specs.example.org/rel/foo"); 58 | assertNotNull(fooResource); 59 | final Map hrefVars = (Map) fooResource.get("href-vars"); 60 | assertEquals(hrefVars.get("fooId"), "http://specs.example.org/rel/foo#fooId"); 61 | assertEquals(fooResource.get("href-template"), "http://example.org/{fooId}"); 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /jsonhome-client/src/main/java/de/otto/jsonhome/client/SimpleJsonHomeClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.client; 18 | 19 | import de.otto.jsonhome.model.JsonHome; 20 | 21 | import java.net.URI; 22 | import java.util.concurrent.ConcurrentHashMap; 23 | import java.util.concurrent.ConcurrentMap; 24 | 25 | /** 26 | * Implementation of the JavaHomeClient interface, serving registered JavaHome documents stored in memory. 27 | * 28 | * This implementation is thread-safe. 29 | * 30 | * @author Guido Steinacker 31 | * @since 26.10.12 32 | */ 33 | public class SimpleJsonHomeClient implements JsonHomeClient { 34 | 35 | private final ConcurrentMap registry = new ConcurrentHashMap(); 36 | 37 | /** 38 | * Registers a JsonHome instance using an URI, uniquely identifying the instance. 39 | * 40 | * Registration of multiple instances using the same URI will only keep the last value. 41 | * 42 | * @param uri the URI of the JsonHome instance. 43 | * @param jsonHome the registered JsonHome instance. 44 | */ 45 | public void register(final URI uri, final JsonHome jsonHome) { 46 | this.registry.put(uri, jsonHome); 47 | } 48 | 49 | /** 50 | * {@inheritDoc} 51 | * 52 | * This method has the same behaviour as {@link #get(java.net.URI)}. If you want to update an already 53 | * registered resource, use {@link #register(java.net.URI, de.otto.jsonhome.model.JsonHome)}. 54 | */ 55 | @Override 56 | public JsonHome updateAndGet(URI uri) { 57 | return get(uri); 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | * 63 | * This implementation simply returns a previously registered instance. 64 | */ 65 | public JsonHome get(final URI uri) { 66 | final JsonHome jsonHome = registry.get(uri); 67 | if (jsonHome != null) { 68 | return jsonHome; 69 | } else { 70 | throw new NotFoundException("JsonHome " + uri.toString() + " not found."); 71 | } 72 | } 73 | 74 | @Override 75 | public void shutdown() { 76 | registry.clear(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | # Version History 2 | 3 | ## Release 0.3.4 4 | * Bugfix: Small change in JacksonJsonHomeParser to be able to use jsonhome 5 | with Java 6 6 | 7 | ## Release 0.3.3 8 | 9 | * Bugfix: Solved problems with duplicate slashes in different URIs 10 | * Bugfix: Using request parameters instead of path variables to specify the registry. Fixed usage of default registries. 11 | 12 | ## Release 0.3.1 13 | 14 | ### 0.3.1 Features 15 | 16 | * Feature: New DocController with Markdown support. This may be used to serve documentation of vendor-specific 17 | media-types, link-relation types, and so on. The DocController is currently available in the jsonhome-spring module 18 | and can also be used in combination with the jsonhome-registry. 19 | * Feature: The accept-ranges hint is now supported. 20 | * Feature: The prefer hint is now supported. 21 | 22 | ### 0.3.1 Known Incompatibilities to 0.3.0 23 | 24 | * There is a new property `jsonhome.docRootDir` that must either be empty (if you are not using Markdown) or 25 | point to the root classpath containing the Markdown documents: `jsonhome.docRootDir=/docs/*` 26 | * Documentation has a new attribute `detailedDescription`. If you have a copy of the FTL templates to 27 | render json-home documents as HTML, you should consider to add the new attribute to your template. 28 | You can find an example in the jsonhome-generator templates (directresource.ftl and templatedresource.ftl) 29 | 30 | ## Release 0.3.0 31 | 32 | With beginning of release 0.3.0, the jsonhome library is used inside the otto.de development. This will bring 33 | the library into a state that is applicable to use it in live real-world applications. 34 | 35 | From now on, this version history will be maintained on a regular basis. Incompatibilities to 36 | earlier versions will be tracked, as well as new features, bug fixes, and so on. 37 | 38 | ### 0.3.0 Features 39 | 40 | * Feature: It is now possible to create multiple registries, containing different sets of json-home documents. 41 | * Feature: The registry is now able to serve json-home documents, describing the link-relations of all registered applications. 42 | * Fearure: Configurable base URIs of href-var types in fragment or sub-resource notation. 43 | This requires a new property jsonhome.varTypeBaseUri to be configured in your application 44 | * Feature: Support of the 'auth-req' hint. 45 | 46 | ### 0.3.0 Known Incompatibilities to earlier versions 47 | 48 | * You must add a new property to your application: jsonhome.varTypeBaseUri must be added to your properties. 49 | The value may be null / empty, in this case the var-type URI is constructed as a fragment of the relation-type URIs as 50 | before. If set to something more meaningful, the href-var type URIs are constructed as a sub-resource of the 51 | relation-type URI. 52 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/converter/JsonHomeConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.converter; 18 | 19 | import de.otto.jsonhome.model.JsonHome; 20 | import de.otto.jsonhome.model.ResourceLink; 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | import static de.otto.jsonhome.converter.JsonHomeMediaType.APPLICATION_JSONHOME; 26 | import static de.otto.jsonhome.converter.ResourceLinkConverter.toRepresentation; 27 | import static java.util.Collections.singletonMap; 28 | 29 | /** 30 | * Converter used to convert JsonHome instances into a map containing the information of a representation. 31 | * 32 | * The result may easily be converted into a format like JSON. 33 | * 34 | * @author Guido Steinacker 35 | * @since 14.10.12 36 | */ 37 | public final class JsonHomeConverter { 38 | 39 | private JsonHomeConverter() {} 40 | 41 | /** 42 | * Converts a JsonHome into json-home representation. 43 | * 44 | * @param jsonHome the JsonHome 45 | * @return Map containing information and structure of a json-home document. 46 | */ 47 | public static Map> toJsonHomeRepresentation(final JsonHome jsonHome) { 48 | return toRepresentation(jsonHome, APPLICATION_JSONHOME); 49 | } 50 | 51 | /** 52 | * Converts a JsonHome into the specified representation. 53 | * 54 | * @param jsonHome the JsonHome 55 | * @param mediaType the media type of the representation 56 | * @return Map containing information and structure specified by the media type. 57 | */ 58 | public static Map> toRepresentation(final JsonHome jsonHome, 59 | final JsonHomeMediaType mediaType) { 60 | final Map jsonResources = new HashMap<>(); 61 | for (final ResourceLink resource : jsonHome.getResources().values()) { 62 | jsonResources.putAll(ResourceLinkConverter.toRepresentation(resource, mediaType)); 63 | } 64 | return singletonMap( 65 | "resources", 66 | jsonResources 67 | ); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /jsonhome-examples/shop/src/main/java/de/otto/jsonhome/example/order/BasketController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.example.order; 17 | 18 | import de.otto.jsonhome.annotation.Auth; 19 | import de.otto.jsonhome.annotation.Doc; 20 | import de.otto.jsonhome.annotation.Hints; 21 | import de.otto.jsonhome.annotation.Rel; 22 | import org.springframework.stereotype.Controller; 23 | import org.springframework.web.bind.annotation.PathVariable; 24 | import org.springframework.web.bind.annotation.RequestMapping; 25 | import org.springframework.web.bind.annotation.RequestMethod; 26 | import org.springframework.web.servlet.ModelAndView; 27 | 28 | 29 | /** 30 | * Controller used to handle requests to the shopping basket of the example web-shop. 31 | *

32 | * TODO Currently not yet implemented. 33 | * 34 | * @author Guido Steinacker 35 | * @since 15.09.12 36 | */ 37 | @Controller 38 | @RequestMapping(value = "/baskets") 39 | @Doc(value = "Shopping basket, used to hold products a customer is about to buy.", 40 | rel = "/rel/get-shopping-basket") 41 | public class BasketController { 42 | 43 | @RequestMapping( 44 | value = "/{basketId}", 45 | method = RequestMethod.GET, 46 | produces = "text/html" 47 | ) 48 | @Rel("/rel/get-shopping-basket") 49 | @Hints(authReq = @Auth(scheme = "Basic", realms = {"foo", "bar"})) 50 | public ModelAndView getBasketAsHtml(@Doc("The unique identifier of the requested shopping basket.") 51 | @PathVariable final long basketId) { 52 | throw new UnsupportedOperationException("not yet implemented"); 53 | } 54 | 55 | @RequestMapping( 56 | value = "/{basketId}", 57 | method = RequestMethod.GET, 58 | produces = "application/json" 59 | ) 60 | @Rel("/rel/get-shopping-basket") 61 | @Hints(authReq = @Auth(scheme = "Basic", realms = {"foo", "bar"})) 62 | public ModelAndView getBasketAsJson(@Doc("The unique identifier of the requested shopping basket.") 63 | @PathVariable final long basketId) { 64 | throw new UnsupportedOperationException("not yet implemented"); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/model/Authentication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | import static java.util.Collections.unmodifiableList; 24 | 25 | /** 26 | * Hints that the resource requires authentication using the HTTP Authentication Framework. 27 | * 28 | * @author Guido Steinacker 29 | * @since 16.02.13 30 | */ 31 | public final class Authentication { 32 | private final String scheme; 33 | private final List realms; 34 | 35 | 36 | private Authentication(final String scheme, final List realms) { 37 | this.scheme = scheme; 38 | this.realms = unmodifiableList(new ArrayList(realms)); 39 | } 40 | 41 | public static Authentication authReq(final String scheme, final List realms) { 42 | return new Authentication(scheme, realms); 43 | } 44 | 45 | public static Authentication authReq(final String scheme) { 46 | return new Authentication(scheme, Collections.emptyList()); 47 | } 48 | 49 | public String getScheme() { 50 | return scheme; 51 | } 52 | 53 | public List getRealms() { 54 | return realms; 55 | } 56 | 57 | @Override 58 | public boolean equals(Object o) { 59 | if (this == o) return true; 60 | if (o == null || getClass() != o.getClass()) return false; 61 | 62 | Authentication auth = (Authentication) o; 63 | 64 | if (realms != null ? !realms.equals(auth.realms) : auth.realms != null) return false; 65 | if (scheme != null ? !scheme.equals(auth.scheme) : auth.scheme != null) return false; 66 | 67 | return true; 68 | } 69 | 70 | @Override 71 | public int hashCode() { 72 | int result = scheme != null ? scheme.hashCode() : 0; 73 | result = 31 * result + (realms != null ? realms.hashCode() : 0); 74 | return result; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "Authentication{" + 80 | "scheme='" + scheme + '\'' + 81 | ", realms=" + realms + 82 | '}'; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /jsonhome-client/src/main/java/de/otto/jsonhome/client/JsonHomeClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.client; 18 | 19 | import de.otto.jsonhome.model.JsonHome; 20 | 21 | import java.net.URI; 22 | 23 | /** 24 | * Client used to retrieve JsonHome documents from different sources. 25 | * 26 | * If the json-home document is retrieved using HTTP GET, the implementation should respect the 27 | * HTTP cache headers returned by the server. 28 | * 29 | * @author Guido Steinacker 30 | * @since 26.10.12 31 | */ 32 | public interface JsonHomeClient { 33 | 34 | /** 35 | * Updates the (possibly cached) JsonHome instance identified by the URI and returns the updated instance. 36 | * 37 | * @param uri the URI uniquely identifying the JsonHome instance. 38 | * @return JsonHome 39 | * @throws NotFoundException if the requested JsonHome was not found. 40 | * @throws JsonHomeClientException different kind of runtime exceptions, depending on the reason why processing of the 41 | * request failed. Most notably: HttpStatusCodeException indication a HTTP client or server error in HTTP based 42 | * implementations of the JsonHomeClient, or IllegalArgumentException in case of an invalid json-home document. 43 | */ 44 | public JsonHome updateAndGet(final URI uri); 45 | 46 | /** 47 | * Gets the JsonHome document associated to the specified URI. 48 | * 49 | * The returned instance may be returned from a cache. 50 | * 51 | * @param uri the URI of the JsonHome document. 52 | * @return JsonHome 53 | * @throws NotFoundException if the requested JsonHome was not found. 54 | * @throws JsonHomeClientException different kind of runtime exceptions, depending on the reason why processing of the 55 | * request failed. Most notably: HttpStatusCodeException indication a HTTP client or server error in HTTP based 56 | * implementations of the JsonHomeClient, or IllegalArgumentException in case of an invalid json-home document. 57 | */ 58 | public JsonHome get(final URI uri); 59 | 60 | /** 61 | * Shutdown the client and dispose all resources. 62 | * 63 | * Should be called when shutting down the client. 64 | */ 65 | public void shutdown(); 66 | } 67 | -------------------------------------------------------------------------------- /jsonhome-spring/src/main/java/de/otto/jsonhome/generator/SpringJsonHomeGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import org.springframework.beans.factory.annotation.Value; 20 | import org.springframework.stereotype.Component; 21 | import org.springframework.stereotype.Controller; 22 | 23 | import javax.annotation.PostConstruct; 24 | import java.net.URI; 25 | 26 | import static org.springframework.core.annotation.AnnotationUtils.findAnnotation; 27 | 28 | /** 29 | * A JsonHomeGenerator used to generate JsonHome objects for Spring-based applications. 30 | * 31 | * @author Guido Steinacker 32 | * @since 17.10.12 33 | */ 34 | @Component 35 | public final class SpringJsonHomeGenerator extends JsonHomeGenerator { 36 | 37 | private URI applicationBaseUri; 38 | private URI relationTypeBaseUri; 39 | private URI varTypeBaseUri; 40 | private String docRootDir; 41 | 42 | @Value("${jsonhome.applicationBaseUri}") 43 | public void setApplicationBaseUri(final String applicationBaseUri) { 44 | this.applicationBaseUri = URI.create(applicationBaseUri); 45 | } 46 | 47 | @Value("${jsonhome.relationTypeBaseUri}") 48 | public void setRelationTypeBaseUri(final String relationTypeBaseUri) { 49 | this.relationTypeBaseUri = URI.create(relationTypeBaseUri); 50 | } 51 | 52 | @Value("${jsonhome.varTypeBaseUri}") 53 | public void setVarTypeBaseUri(final String varTypeBaseUri) { 54 | if (varTypeBaseUri != null && !varTypeBaseUri.isEmpty()) { 55 | this.varTypeBaseUri = URI.create(varTypeBaseUri); 56 | } 57 | } 58 | 59 | @Value("${jsonhome.docRootDir}") 60 | public void setDocRootDir(String docRootDir) { 61 | this.docRootDir = docRootDir; 62 | } 63 | 64 | @PostConstruct 65 | public void postConstruct() { 66 | setResourceLinkGenerator(new SpringResourceLinkGenerator( 67 | applicationBaseUri, 68 | relationTypeBaseUri, 69 | varTypeBaseUri, 70 | docRootDir) 71 | ); 72 | } 73 | 74 | @Override 75 | protected boolean isCandidateForAnalysis(final Class controller) { 76 | return findAnnotation(controller, Controller.class) != null; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/test/java/de/otto/jsonhome/generator/JerseyResourceLinkGeneratorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import de.otto.jsonhome.annotation.Rel; 20 | import de.otto.jsonhome.model.ResourceLink; 21 | import org.testng.annotations.Test; 22 | 23 | import javax.ws.rs.GET; 24 | import javax.ws.rs.Path; 25 | import java.lang.reflect.Method; 26 | 27 | import static de.otto.jsonhome.fixtures.ResourceFixtures.ResourceWithResourceAndLinkRelationType; 28 | import static java.net.URI.create; 29 | import static org.testng.Assert.assertTrue; 30 | import static org.testng.AssertJUnit.assertEquals; 31 | import static org.testng.AssertJUnit.assertFalse; 32 | 33 | public class JerseyResourceLinkGeneratorTest { 34 | 35 | private static @Path("/test") class ResourceWithTemplateLinkWithExtension { 36 | @GET @Path("/foo/{bar}.xml") @Rel("http://example.org/rel/foo/bar") 37 | public void getSomething() {} 38 | } 39 | 40 | @Test 41 | public void testPathsWithLeadingAndTrailingSlashes() throws Exception { 42 | final ResourceLinkGenerator generator = new JerseyResourceLinkGenerator( 43 | create("http://example.org"), 44 | create("http://rel.example.org"), 45 | null, null 46 | ); 47 | final String resource = generator.resourcePathFor( 48 | ResourceWithResourceAndLinkRelationType.class.getMethod("bar") 49 | ); 50 | assertEquals("http://example.org/foo/bar/", resource); 51 | } 52 | 53 | @Test 54 | public void shouldBeTemplateLink() throws Exception { 55 | // given 56 | final JerseyResourceLinkGenerator generator = new JerseyResourceLinkGenerator( 57 | create("http://example.org"), 58 | create("http://rel.example.org"), 59 | null, null 60 | ); 61 | final Method method = ResourceWithTemplateLinkWithExtension.class.getMethod("getSomething"); 62 | // when 63 | final boolean isCandidateForAnalysis = generator.isCandidateForAnalysis(method); 64 | final ResourceLink resourceLink = generator.resourceLinkFor(method); 65 | // then 66 | assertTrue(isCandidateForAnalysis); 67 | assertFalse(resourceLink.isDirectLink()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /jsonhome-generator/src/main/resources/jsonhome/freemarker/templatedresource.ftl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | json-home 7 | 8 | 9 | 10 |

${resource.linkRelationType}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 73 | 74 | <#include "hints-rows.ftl"> 75 | 76 | 77 | 78 | 79 | 80 | 81 |
AttributeValueDescription
Rel${resource.linkRelationType} 25 | <#list resource.hints.docs.description as descr> 26 |

${descr}

27 | 28 | <#if resource.hints.docs.detailedDescription?has_content> 29 | ${resource.hints.docs.detailedDescription} 30 |
31 | 32 | <#if resource.hints.docs.link?has_content> 33 |

See ${resource.hints.docs.link}

34 | 35 |
Href-template${resource.hrefTemplate}The href-template used to build links to the resource.
Href-vars 45 | 46 | 47 | 48 | 49 | 50 | 51 | <#list resource.hrefVars as hrefVar> 52 | 53 | 54 | 55 | 69 | 70 | 71 |
VariableTypeDescription
${hrefVar.var}${hrefVar.varType} 56 | <#if hrefVar.docs.hasDescription()> 57 | <#list hrefVar.docs.description as descr> 58 |

${descr}

59 | 60 | 61 | <#if hrefVar.docs.hasDetailedDescription()> 62 | ${hrefVar.docs.detailedDescription} 63 |
64 | 65 | <#if hrefVar.docs.hasLink()> 66 |

See ${hrefVar.docs.link}

67 | 68 |
72 |
 
82 | 83 | -------------------------------------------------------------------------------- /jsonhome-client/src/test/java/de/otto/jsonhome/client/HttpJsonHomeClientTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.client; 18 | 19 | import de.otto.jsonhome.model.JsonHome; 20 | import org.testng.annotations.Test; 21 | 22 | import java.net.URI; 23 | 24 | import static java.net.URI.create; 25 | import static org.testng.Assert.*; 26 | 27 | /** 28 | * @author Guido Steinacker 29 | * @since 26.10.12 30 | */ 31 | public class HttpJsonHomeClientTest { 32 | 33 | public static final URI RELATION_TYPE_URI = create("http://localhost:8080/jsonhome-example/rel/products"); 34 | public static final URI JSONHOME_URI = create("http://localhost:8080/jsonhome-example/json-home"); 35 | 36 | // TODO: implement and use harness server 37 | @Test(enabled = false) 38 | public void shouldFindRegisteredResource() { 39 | // given 40 | final JsonHomeClient client = new HttpJsonHomeClient(); 41 | // when 42 | final JsonHome jsonHome = client.get(JSONHOME_URI); 43 | // then 44 | assertNotNull(jsonHome); 45 | assertTrue(jsonHome.hasResourceFor(RELATION_TYPE_URI)); 46 | } 47 | 48 | // TODO: implement and use harness server 49 | // TODO: caching-behaviour is not testable 50 | @Test(enabled = false) 51 | public void shouldInvalidateCacheEntry() { 52 | // given 53 | final JsonHomeClient client = new HttpJsonHomeClient(); 54 | // when 55 | client.get(JSONHOME_URI); 56 | client.get(JSONHOME_URI); 57 | final JsonHome jsonHome = client.updateAndGet(JSONHOME_URI); 58 | // then 59 | assertNotNull(jsonHome); 60 | assertTrue(jsonHome.hasResourceFor(RELATION_TYPE_URI)); 61 | } 62 | 63 | // TODO: implement and use harness server 64 | @Test(enabled = false, expectedExceptions = NotFoundException.class) 65 | public void shouldThrowNotFoundExceptionForUnknownResource() { 66 | // given 67 | final JsonHomeClient client = new HttpJsonHomeClient(); 68 | // when 69 | final JsonHome jsonHome = client.get(URI.create("http://localhost:8080/foo")); 70 | // then 71 | assertNull(jsonHome); 72 | } 73 | 74 | @Test(enabled = false) 75 | public void shouldGetApplicationJsonFormatIncludingDescription() { 76 | fail(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /jsonhome-registry/src/main/java/de/otto/jsonhome/registry/store/Link.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.store; 18 | 19 | import java.net.URI; 20 | 21 | /** 22 | * A link to a resource, consisting of a title and href. 23 | * 24 | * @author Guido Steinacker 25 | * @since 14.11.12 26 | */ 27 | public final class Link { 28 | 29 | private final String title; 30 | private final URI href; 31 | 32 | /** 33 | * Creates a new link to a resource. 34 | * 35 | * @param href the URI of the linked json-home document. 36 | * @param title the title of the link. 37 | */ 38 | public Link(final URI href, 39 | final String title) { 40 | if (href == null) { 41 | throw new NullPointerException("'href' must not be null."); 42 | } 43 | if (!href.isAbsolute()) { 44 | throw new IllegalArgumentException("'href' must be an absolute URI."); 45 | } 46 | this.title = title != null ? title : ""; 47 | this.href = href; 48 | } 49 | 50 | /** 51 | * Title of the system offering the json-home document. 52 | * 53 | * @return String 54 | */ 55 | public String getTitle() { 56 | return title; 57 | } 58 | 59 | /** 60 | * The URI of the referred json-home document. 61 | * 62 | * @return absolute URI. 63 | */ 64 | public URI getHref() { 65 | return href; 66 | } 67 | 68 | @Override 69 | public boolean equals(Object o) { 70 | if (this == o) return true; 71 | if (o == null || getClass() != o.getClass()) return false; 72 | 73 | Link link = (Link) o; 74 | 75 | if (href != null ? !href.equals(link.href) : link.href != null) return false; 76 | if (title != null ? !title.equals(link.title) : link.title != null) return false; 77 | 78 | return true; 79 | } 80 | 81 | @Override 82 | public int hashCode() { 83 | int result = title != null ? title.hashCode() : 0; 84 | result = 31 * result + (href != null ? href.hashCode() : 0); 85 | return result; 86 | } 87 | 88 | @Override 89 | public String toString() { 90 | return "Link{" + 91 | "title='" + title + '\'' + 92 | ", href=" + href + 93 | '}'; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /jsonhome-registry/src/main/java/de/otto/jsonhome/registry/controller/RegistryConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.controller; 18 | 19 | import de.otto.jsonhome.registry.store.Link; 20 | import de.otto.jsonhome.registry.store.Registry; 21 | 22 | import java.net.URI; 23 | import java.util.ArrayList; 24 | import java.util.LinkedHashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.stream.Collectors; 28 | 29 | import static de.otto.jsonhome.registry.controller.LinkConverter.jsonToLink; 30 | import static de.otto.jsonhome.registry.controller.LinkConverter.linkToJson; 31 | import static java.util.stream.Collectors.toList; 32 | 33 | /** 34 | * A converter used to convert Registry and Link items into maps and vice versa. 35 | * 36 | * @author Guido Steinacker 37 | * @since 14.11.12 38 | */ 39 | public class RegistryConverter { 40 | 41 | private RegistryConverter() {} 42 | 43 | public static Registry jsonToRegistry(final Map map) { 44 | try { 45 | @SuppressWarnings("unchecked") 46 | final List> linksMap = (List>) map.get("service"); 47 | return new Registry( 48 | (String) map.get("name"), 49 | (String) map.get("title"), 50 | linksMap 51 | .stream() 52 | .map(LinkConverter::jsonToLink) 53 | .collect(toList()) 54 | ); 55 | } catch (final NullPointerException e) { 56 | throw new IllegalArgumentException("Map does not contain valid links", e); 57 | } 58 | } 59 | 60 | public static Map registryToJson(final URI baseUri, final Registry registry) { 61 | final Map content = new LinkedHashMap<>(); 62 | content.put("name", registry.getName()); 63 | content.put("title", registry.getTitle()); 64 | content.put("self", baseUri + "/registries/" + registry.getName()); 65 | content.put("container", baseUri + "/registries"); 66 | content.put("service", registry.getAll() 67 | .stream() 68 | .map(LinkConverter::linkToJson) 69 | .collect(toList())); 70 | return content; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/generator/JerseyJsonHomeGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import de.otto.jsonhome.JsonHomeProperties; 20 | 21 | import javax.ws.rs.Path; 22 | import java.net.URI; 23 | import java.util.Properties; 24 | 25 | import static java.net.URI.create; 26 | 27 | /** 28 | * @author Sebastian Schroeder 29 | * @since 09.12.2012 30 | */ 31 | public final class JerseyJsonHomeGenerator extends JsonHomeGenerator { 32 | 33 | public JerseyJsonHomeGenerator() { 34 | final Properties properties = JsonHomeProperties.getProperties(); 35 | final String applicationBaseUri = properties.getProperty("applicationBaseUri"); 36 | if (applicationBaseUri == null) { 37 | throw new IllegalStateException("applicationBaseUri property not set in jsonhome.properties"); 38 | } 39 | final String relationTypeBaseUri = properties.getProperty("relationTypeBaseUri"); 40 | if (relationTypeBaseUri == null) { 41 | throw new IllegalStateException("relationTypeBaseUri property not set in jsonhome.properties"); 42 | } 43 | final String varTypeBaseUri = properties.getProperty("varTypeBaseUri", null); 44 | final String docRootDir = properties.getProperty("docRootDir", null); 45 | setResourceLinkGenerator(new JerseyResourceLinkGenerator( 46 | create(applicationBaseUri), 47 | create(relationTypeBaseUri), 48 | varTypeBaseUri != null ? create(varTypeBaseUri) : null, 49 | docRootDir)); 50 | } 51 | 52 | JerseyJsonHomeGenerator(URI applicationBaseUri, URI relationTypeBaseUri) { 53 | setResourceLinkGenerator(new JerseyResourceLinkGenerator(applicationBaseUri, relationTypeBaseUri, null, null)); 54 | } 55 | 56 | public JerseyJsonHomeGenerator(String applicationBaseUri, String relationTypeBaseUri) { 57 | this(create(applicationBaseUri), create(relationTypeBaseUri)); 58 | } 59 | 60 | /** 61 | * Returns true if the resource is a candidate for further processing, false otherwise. 62 | * 63 | * @param resource the resource to check 64 | * @return boolean 65 | */ 66 | @Override 67 | protected boolean isCandidateForAnalysis(Class resource) { 68 | return resource.getAnnotation(Path.class) != null; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /jsonhome-core/src/test/java/de/otto/jsonhome/converter/JsonHomeConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.converter; 18 | 19 | import de.otto.jsonhome.model.JsonHome; 20 | import de.otto.jsonhome.model.ResourceLink; 21 | import org.testng.annotations.Test; 22 | 23 | import java.util.List; 24 | import java.util.Map; 25 | 26 | import static de.otto.jsonhome.converter.JsonHomeConverter.toJsonHomeRepresentation; 27 | import static de.otto.jsonhome.converter.JsonHomeMediaType.APPLICATION_JSONHOME; 28 | import static de.otto.jsonhome.converter.ResourceLinkConverter.toRepresentation; 29 | import static de.otto.jsonhome.fixtures.LinkFixtures.ABOUTPAGE_LINK; 30 | import static de.otto.jsonhome.fixtures.LinkFixtures.STOREFRONT_LINK; 31 | import static de.otto.jsonhome.model.JsonHome.jsonHome; 32 | import static java.util.Arrays.asList; 33 | import static org.testng.Assert.*; 34 | 35 | /** 36 | * @author Guido Steinacker 37 | * @since 14.10.12 38 | */ 39 | public class JsonHomeConverterTest { 40 | @Test 41 | public void shouldRenderEmptyJsonHome() { 42 | // given 43 | final List resourceLinks = asList(STOREFRONT_LINK, ABOUTPAGE_LINK); 44 | final JsonHome jsonHome = jsonHome(resourceLinks); 45 | // when 46 | final Map json = toJsonHomeRepresentation(jsonHome); 47 | // then 48 | assertNotNull(json); 49 | } 50 | 51 | @Test 52 | public void shouldRenderJsonHomeWithTwoDirectLinks() { 53 | // given 54 | final List resourceLinks = asList(STOREFRONT_LINK, ABOUTPAGE_LINK); 55 | final JsonHome jsonHome = jsonHome(resourceLinks); 56 | // when 57 | final Map json = toJsonHomeRepresentation(jsonHome); 58 | // then 59 | assertTrue(json.containsKey("resources")); 60 | assertTrue(Map.class.isAssignableFrom(json.get("resources").getClass())); 61 | @SuppressWarnings("unchecked") 62 | final Map resources = (Map) json.get("resources"); 63 | String relationType = STOREFRONT_LINK.getLinkRelationType().toString(); 64 | assertEquals(resources.get(relationType), toRepresentation(STOREFRONT_LINK, APPLICATION_JSONHOME).get(relationType)); 65 | relationType = ABOUTPAGE_LINK.getLinkRelationType().toString(); 66 | assertEquals(resources.get(relationType), toRepresentation(ABOUTPAGE_LINK, APPLICATION_JSONHOME).get(relationType)); 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/resource/RelationResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.resource; 18 | 19 | import com.sun.jersey.api.view.Viewable; 20 | import de.otto.jsonhome.generator.JerseyJsonHomeGenerator; 21 | import de.otto.jsonhome.generator.JsonHomeSource; 22 | import de.otto.jsonhome.model.JsonHome; 23 | import de.otto.jsonhome.model.ResourceLink; 24 | import de.otto.jsonhome.resource.scanner.AnnotationScanner; 25 | 26 | import javax.ws.rs.GET; 27 | import javax.ws.rs.Path; 28 | import javax.ws.rs.Produces; 29 | import javax.ws.rs.core.Context; 30 | import javax.ws.rs.core.MediaType; 31 | import javax.ws.rs.core.Response; 32 | import javax.ws.rs.core.UriInfo; 33 | import java.util.HashMap; 34 | import java.util.Map; 35 | 36 | import static de.otto.jsonhome.resource.Responses.addCacheControlHeaders; 37 | 38 | /** 39 | * @author Sebastian Schroeder 40 | * @since 28.12.2012 41 | */ 42 | @Path("/rel/{all:.*}") 43 | public final class RelationResource { 44 | 45 | private final JsonHomeSource jsonHomeSource; 46 | private int maxAge = 3600; 47 | 48 | public RelationResource(JsonHomeSource jsonHomeSource) { 49 | this.jsonHomeSource = jsonHomeSource; 50 | } 51 | 52 | public RelationResource() { 53 | this.jsonHomeSource = new JerseyJsonHomeSource(new JerseyJsonHomeGenerator(), new AnnotationScanner()); 54 | } 55 | 56 | public void setMaxAge(int maxAge) { 57 | this.maxAge = maxAge; 58 | } 59 | 60 | @GET 61 | @Produces(MediaType.TEXT_HTML) 62 | public Response getRelationType(@Context UriInfo uriInfo) { 63 | final Map model = new HashMap(); 64 | final JsonHome jsonHome = jsonHomeSource.getJsonHome(); 65 | if (jsonHome.hasResourceFor(uriInfo.getRequestUri())) { 66 | final ResourceLink resourceLink = jsonHome.getResourceFor(uriInfo.getRequestUri()); 67 | model.put("resource", resourceLink); 68 | final Viewable viewable; 69 | if (resourceLink.isDirectLink()) { 70 | viewable = new Viewable("/jsonhome/directresource", model); 71 | } else { 72 | viewable = new Viewable("/jsonhome/templatedresource", model); 73 | } 74 | return addCacheControlHeaders(Response.ok(viewable), maxAge); 75 | } else { 76 | return Response.status(Response.Status.NOT_FOUND).entity("Unknown relation type " + uriInfo.getRequestUri()).build(); 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/model/ResourceLink.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.model; 17 | 18 | import java.net.URI; 19 | 20 | /** 21 | * A direct or templated resource link. 22 | * 23 | * @see http://tools.ietf.org/html/draft-nottingham-json-home-02 24 | * @author Guido Steinacker 25 | * @since 16.09.12 26 | */ 27 | public interface ResourceLink { 28 | 29 | /** 30 | * The link-relation type of the resource link 31 | * 32 | * @return URI of the link-relation type. 33 | * @see http://tools.ietf.org/html/rfc5988 34 | */ 35 | public URI getLinkRelationType(); 36 | 37 | /** 38 | * Returns the hints of a ResourceLink object. 39 | * 40 | * @return hints 41 | * @see http://tools.ietf.org/html/draft-nottingham-json-home-02#section-5 42 | */ 43 | public Hints getHints(); 44 | 45 | /** 46 | * @return true, if the resource link is a direct link, false if it is a templated link. 47 | */ 48 | public boolean isDirectLink(); 49 | 50 | /** 51 | * Returns the ResourceLink as a TemplatedLink. 52 | * 53 | * @return TemplatedLink 54 | * @throws IllegalStateException if this resource is a DirectLink. 55 | */ 56 | public TemplatedLink asTemplatedLink(); 57 | 58 | /** 59 | * Returns this ResourceLink as a DirectLink. 60 | * 61 | * @return DirectLink 62 | * @throws IllegalStateException if this resource is a TemplatedLink. 63 | */ 64 | public DirectLink asDirectLink(); 65 | 66 | /** 67 | * Merges this resource link with another one and returns a new instance. 68 | * 69 | * There are a number of restrictions that must be met by the other ResourceLink: 70 | *
    71 | *
  • Both links must be of the same kind: either both DirectLinks or both TemplatedLinks
  • 72 | *
  • The two link-relation types must be equal
  • 73 | *
  • If both links are direct, the href must be equal.
  • 74 | *
  • If both links are templated, the href-template and ref-vars must be equal.
  • 75 | *
76 | * Basically, only the hints are merged. 77 | * 78 | * @param other the other resource link 79 | * @return a new, merged ResourceLink instance 80 | */ 81 | public ResourceLink mergeWith(ResourceLink other); 82 | 83 | } 84 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/converter/ResourceLinkConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.converter; 18 | 19 | import de.otto.jsonhome.model.DirectLink; 20 | import de.otto.jsonhome.model.HrefVar; 21 | import de.otto.jsonhome.model.ResourceLink; 22 | import de.otto.jsonhome.model.TemplatedLink; 23 | 24 | import java.util.Collections; 25 | import java.util.LinkedHashMap; 26 | import java.util.Map; 27 | 28 | /** 29 | * Converter used to convert a ResourceLink into a json-home resource. 30 | * 31 | * @author Guido Steinacker 32 | * @since 14.10.12 33 | */ 34 | public final class ResourceLinkConverter { 35 | 36 | public static Map> toRepresentation(final ResourceLink resourceLink, 37 | final JsonHomeMediaType mediaType) { 38 | if (resourceLink.isDirectLink()) { 39 | return directLinkToJsonHome(resourceLink.asDirectLink(), mediaType); 40 | } else { 41 | return templatedLinkToJsonHome(resourceLink.asTemplatedLink(), mediaType); 42 | } 43 | } 44 | 45 | public static Map> templatedLinkToJsonHome(final TemplatedLink resourceLink, 46 | final JsonHomeMediaType mediaType) { 47 | final Map jsonHrefVars = new LinkedHashMap<>(); 48 | for (final HrefVar hrefVar : resourceLink.getHrefVars()) { 49 | jsonHrefVars.put(hrefVar.getVar(), hrefVar.getVarType().toString()); 50 | } 51 | 52 | final Map map = new LinkedHashMap<>(); 53 | map.put("href-template", resourceLink.getHrefTemplate()); 54 | map.put("href-vars", jsonHrefVars); 55 | map.put("hints", HintsConverter.toRepresentation(resourceLink.getHints(), mediaType)); 56 | return Collections.singletonMap(resourceLink.getLinkRelationType().toString(), map); 57 | } 58 | 59 | public static Map> directLinkToJsonHome(final DirectLink resourceLink, 60 | final JsonHomeMediaType mediaType) { 61 | final Map map = new LinkedHashMap<>(); 62 | map.put("href", resourceLink.getHref().toString()); 63 | map.put("hints", HintsConverter.toRepresentation(resourceLink.getHints(), mediaType)); 64 | return Collections.singletonMap(resourceLink.getLinkRelationType().toString(), map); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /jsonhome-registry/src/test/java/de/otto/jsonhome/registry/fixture/RegistriesFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.fixture; 18 | 19 | import de.otto.jsonhome.registry.store.Link; 20 | 21 | import java.util.*; 22 | 23 | import static de.otto.jsonhome.registry.controller.LinkConverter.linkToJson; 24 | import static java.net.URI.create; 25 | import static java.util.Collections.singletonMap; 26 | 27 | /** 28 | * @author Guido Steinacker 29 | * @since 04.02.13 30 | */ 31 | public class RegistriesFixture { 32 | 33 | /** 34 | * { 35 | * "self" : "http://example.org/registries", 36 | * "registries" : [] 37 | * } 38 | */ 39 | public static Map emptyRegistries() { 40 | final Map map = new HashMap(); 41 | map.put("self", "http://example.org/registries"); 42 | map.put("registries", Collections.emptyList()); 43 | return map; 44 | } 45 | 46 | /** 47 | * { 48 | * "self" : "http://example.org/registries", 49 | * "registries" : [ 50 | * {"href" : "http://example.org/registries/live"} 51 | * ] 52 | * } 53 | */ 54 | public static Map oneRegistryNamed(final String registryName) { 55 | final Map map = new HashMap(); 56 | map.put("self", "http://example.org/registries"); 57 | map.put("registries", Collections.>singletonList( 58 | linkToJson(new Link( 59 | create("http://example.org/registries/" + registryName), 60 | "Registry of the " + registryName + " environment")) 61 | )); 62 | return map; 63 | } 64 | 65 | /** 66 | * { 67 | * "self" : "http://example.org/registries", 68 | * "registries" : [ 69 | * {"href" : "http://example.org/registries/test"}, 70 | * {"href" : "http://example.org/registries/live"} 71 | * ] 72 | * } 73 | */ 74 | public static Map twoRegistriesTestAndLive() { 75 | final Map map = new HashMap(); 76 | map.put("self", "http://example.org/registries"); 77 | final List> registries = new ArrayList>(); 78 | registries.add(singletonMap("href", "http://example.org/registries/test")); 79 | registries.add(singletonMap("href", "http://example.org/registries/live")); 80 | map.put("registries", registries); 81 | return map; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /jsonhome-core/src/main/java/de/otto/jsonhome/model/ResourceLinkHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.otto.jsonhome.model; 17 | 18 | import java.net.URI; 19 | import java.util.ArrayList; 20 | import java.util.LinkedHashMap; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | /** 25 | * A helper class used to handle ResourceLink instances. 26 | */ 27 | public final class ResourceLinkHelper { 28 | 29 | private ResourceLinkHelper() { 30 | } 31 | 32 | public static List mergeResources(final List resourceLinks, 33 | final List other) { 34 | if (other.isEmpty()) { 35 | return resourceLinks; 36 | } else { 37 | List result = resourceLinks; 38 | for (final ResourceLink resourceLink : other) { 39 | result = mergeResources(result, resourceLink); 40 | } 41 | return result; 42 | } 43 | } 44 | 45 | /** 46 | * Merges two lists of ResourceLinks into one list of {@link ResourceLink#mergeWith(de.otto.jsonhome.model.ResourceLink) merged} instances. 47 | * 48 | * @param resourceLinks the list of resource links. This list will not be modified. 49 | * @param other the other list of resource links. This list will not be modified. 50 | * @return a list of merged resource links. 51 | */ 52 | public static List mergeResources(final List resourceLinks, 53 | final ResourceLink other) { 54 | final List allCandidates = new ArrayList(resourceLinks); 55 | if (other != null) { 56 | allCandidates.add(other); 57 | } 58 | final Map resourceLinkCandidates = new LinkedHashMap(); 59 | for (final ResourceLink candidate : allCandidates) { 60 | final URI linkRelationType = candidate.getLinkRelationType(); 61 | final ResourceLink existingCandidate = resourceLinkCandidates.get(linkRelationType); 62 | if (existingCandidate != null) { 63 | // merge the candidates, they are belonging to the same resource link 64 | resourceLinkCandidates.put(linkRelationType, existingCandidate.mergeWith(candidate)); 65 | } else { 66 | resourceLinkCandidates.put(linkRelationType, candidate); 67 | } 68 | } 69 | return new ArrayList(resourceLinkCandidates.values()); 70 | } 71 | } -------------------------------------------------------------------------------- /jsonhome-registry/src/main/java/de/otto/jsonhome/registry/store/Registry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.registry.store; 18 | 19 | import java.net.URI; 20 | import java.util.ArrayList; 21 | import java.util.Collection; 22 | import java.util.List; 23 | 24 | import static java.util.Collections.unmodifiableList; 25 | 26 | /** 27 | * An immutable named collection of Registry. 28 | * 29 | * @author Guido Steinacker 30 | * @since 14.11.12 31 | */ 32 | public final class Registry { 33 | 34 | private final String name; 35 | private final String title; 36 | private final List links; 37 | 38 | public Registry(final String name, final String title, final List links) { 39 | if (name == null) { 40 | throw new NullPointerException("Name of Links must not be null"); 41 | } 42 | if (name.isEmpty()) { 43 | throw new IllegalArgumentException("Name of Links must not be empty"); 44 | } 45 | this.name = name; 46 | this.title = title; 47 | this.links = unmodifiableList(new ArrayList<>(links)); 48 | } 49 | 50 | /** 51 | * Returns the name of the link collection. 52 | * 53 | * @return name of the links; 54 | */ 55 | public String getName() { 56 | return name; 57 | } 58 | 59 | /** 60 | * Returns the human-readable title of the registry. 61 | * 62 | * @return title 63 | */ 64 | public String getTitle() { 65 | return title; 66 | } 67 | 68 | /** 69 | * Returns an unmodifiable collection of all registered links. 70 | * 71 | * @return collection of entries. 72 | */ 73 | public Collection getAll() { 74 | return links; 75 | } 76 | 77 | /** 78 | * Returns the entry referring to the specified href. 79 | * 80 | * @param href URI of the link. 81 | * @return Link 82 | */ 83 | public Link findByHref(final URI href) { 84 | for (final Link link : links) { 85 | if (link.getHref().equals(href)) { 86 | return link; 87 | } 88 | } 89 | return null; 90 | } 91 | 92 | public Link asLinkFor(final URI baseUri) { 93 | final URI uri; 94 | if (baseUri.toString().endsWith("/")) { 95 | uri = baseUri.resolve("registries/" + name); 96 | } else { 97 | uri = URI.create(baseUri.toString() + "/registries/" + name); 98 | } 99 | return new Link( 100 | uri, 101 | title 102 | ); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /jsonhome-spring/src/test/java/de/otto/jsonhome/controller/HtmlControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.controller; 18 | 19 | import de.otto.jsonhome.generator.JsonHomeGenerator; 20 | import de.otto.jsonhome.generator.JsonHomeSource; 21 | import de.otto.jsonhome.generator.SpringJsonHomeGenerator; 22 | import de.otto.jsonhome.model.DirectLink; 23 | import org.springframework.mock.web.MockHttpServletRequest; 24 | import org.springframework.web.servlet.ModelAndView; 25 | import org.testng.annotations.Test; 26 | 27 | import java.net.URI; 28 | 29 | import static de.otto.jsonhome.fixtures.ControllerFixtures.ControllerWithRequestMappingAndLinkRelationTypeAtClassLevel; 30 | import static org.testng.Assert.assertEquals; 31 | import static org.testng.Assert.assertNotNull; 32 | 33 | /** 34 | * @author Guido Steinacker 35 | * @since 05.10.12 36 | */ 37 | public class HtmlControllerTest { 38 | 39 | @Test 40 | public void testGetRel() throws Exception { 41 | // given 42 | final HtmlController controller = relController(ControllerWithRequestMappingAndLinkRelationTypeAtClassLevel.class); 43 | // when 44 | final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/rel/foo"); 45 | request.setServerName("rel.example.org"); 46 | request.setScheme("http"); 47 | final ModelAndView resourcesMap = controller.getRelationshipType(request); 48 | // then 49 | assertEquals(resourcesMap.getViewName(), "directresource"); 50 | assertNotNull(resourcesMap.getModel().get("resource")); 51 | @SuppressWarnings("unchecked") 52 | final DirectLink model = (DirectLink) resourcesMap.getModel().get("resource"); 53 | assertEquals(model.getHref(), URI.create("http://app.example.org/bar")); 54 | } 55 | 56 | private HtmlController relController(final Class controllerType) { 57 | final HtmlController controller = new HtmlController(); 58 | controller.setJsonHomeSource(getJsonHomeSource(controllerType)); 59 | controller.setRelationTypeBaseUri("http://rel.example.org/"); 60 | return controller; 61 | } 62 | 63 | private JsonHomeSource getJsonHomeSource(final Class controllerType) { 64 | final GeneratorBasedJsonHomeSource source = new GeneratorBasedJsonHomeSource(); 65 | source.setControllerTypes(controllerType); 66 | source.setJsonHomeGenerator(jsonHomeGenerator()); 67 | return source; 68 | } 69 | 70 | private JsonHomeGenerator jsonHomeGenerator() { 71 | final SpringJsonHomeGenerator jsonHomeGenerator = new SpringJsonHomeGenerator(); 72 | jsonHomeGenerator.setApplicationBaseUri("http://app.example.org"); 73 | jsonHomeGenerator.setRelationTypeBaseUri("http://rel.example.org"); 74 | jsonHomeGenerator.postConstruct(); 75 | return jsonHomeGenerator; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /jsonhome-core/src/test/java/de/otto/jsonhome/converter/ResourceLinkConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.converter; 18 | 19 | import de.otto.jsonhome.model.DirectLink; 20 | import de.otto.jsonhome.model.TemplatedLink; 21 | import org.testng.annotations.Test; 22 | 23 | import java.util.Arrays; 24 | import java.util.Map; 25 | 26 | import static de.otto.jsonhome.converter.JsonHomeMediaType.APPLICATION_JSONHOME; 27 | import static de.otto.jsonhome.converter.ResourceLinkConverter.toRepresentation; 28 | import static de.otto.jsonhome.fixtures.LinkFixtures.*; 29 | import static de.otto.jsonhome.model.Allow.GET; 30 | import static java.util.Collections.singletonMap; 31 | import static java.util.EnumSet.of; 32 | import static org.testng.Assert.*; 33 | 34 | /** 35 | * @author Guido Steinacker 36 | * @since 14.10.12 37 | */ 38 | public class ResourceLinkConverterTest { 39 | 40 | @Test 41 | public void shouldConvertDirectLink() { 42 | // given 43 | final DirectLink storefrontLink = STOREFRONT_LINK; 44 | // when 45 | final Map json = toRepresentation(storefrontLink, APPLICATION_JSONHOME); 46 | // then 47 | assertNotNull(json); 48 | assertEquals(json.keySet().size(), 1); 49 | @SuppressWarnings("unchecked") 50 | final Map resource = (Map) json.get("http://example.org/json-home/rel/shop/storefront"); 51 | assertEquals(resource.keySet().size(), 2); 52 | assertEquals(resource.get("href"), ABS_STOREFRONT_HREF.toString()); 53 | final Map hints = (Map) resource.get("hints"); 54 | assertNotNull(hints); 55 | assertEquals(hints.get("allow"), of(GET)); 56 | assertEquals(hints.get("representations"), Arrays.asList("text/html", "application/json")); 57 | } 58 | 59 | @Test 60 | public void shouldConvertTemplatedLink() { 61 | // given 62 | final TemplatedLink aboutPageLink = ABOUTPAGE_LINK; 63 | // when 64 | Map json = toRepresentation(aboutPageLink, APPLICATION_JSONHOME); 65 | // then 66 | assertNotNull(json); 67 | assertEquals(json.keySet().size(), 1); 68 | @SuppressWarnings("unchecked") 69 | final Map resource = (Map) json.get("http://example.org/json-home/rel/shop/page"); 70 | assertEquals(resource.keySet().size(), 3); 71 | assertNull(resource.get("href")); 72 | assertEquals(resource.get("href-template"), REL_PAGE_HREF); 73 | assertEquals(resource.get("href-vars"), singletonMap("pageId", "http://example.org/json-home/vartype/shop/page/pageId")); 74 | final Map hints = (Map) resource.get("hints"); 75 | assertNotNull(hints); 76 | assertEquals(hints.get("allow"), of(GET)); 77 | assertEquals(hints.get("representations"), Arrays.asList("text/html", "application/json")); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /jsonhome-core/src/test/java/de/otto/jsonhome/model/ResourceLinkHelperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.model; 18 | 19 | import org.testng.annotations.Test; 20 | 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | import static de.otto.jsonhome.fixtures.LinkFixtures.*; 25 | import static de.otto.jsonhome.model.ResourceLinkHelper.mergeResources; 26 | import static java.util.Arrays.asList; 27 | import static org.testng.Assert.assertEquals; 28 | 29 | /** 30 | * @author Guido Steinacker 31 | * @since 27.12.12 32 | */ 33 | public class ResourceLinkHelperTest { 34 | 35 | @Test 36 | public void mergingIdenticalLinksShouldResultInSingleLink() throws Exception { 37 | // when 38 | final List resourceLinks = mergeResources( 39 | asList(STOREFRONT_LINK), 40 | STOREFRONT_LINK 41 | ); 42 | // then 43 | assertEquals(resourceLinks, asList(STOREFRONT_LINK)); 44 | } 45 | 46 | @Test 47 | public void mergingDifferentLinksShouldResultInMergedLinks() throws Exception { 48 | // when 49 | final List resourceLinks = mergeResources( 50 | asList(STOREFRONT_LINK), 51 | ABOUTPAGE_LINK 52 | ); 53 | // then 54 | assertEquals(resourceLinks, asList(STOREFRONT_LINK, ABOUTPAGE_LINK)); 55 | } 56 | 57 | @Test 58 | public void mergingListWithIdenticalLinksShouldResultInSingleLink() throws Exception { 59 | // when 60 | final List resourceLinks = mergeResources( 61 | asList(STOREFRONT_LINK), 62 | asList(STOREFRONT_LINK) 63 | ); 64 | // then 65 | assertEquals(resourceLinks, asList(STOREFRONT_LINK)); 66 | } 67 | 68 | @Test 69 | public void mergingListsWithDifferentLinksShouldResultInMergedLinks() throws Exception { 70 | // when 71 | final List first = asList(STOREFRONT_LINK, ABOUTPAGE_LINK); 72 | final List second = asList(SHOPPAGES_LINK, FOO_LINK); 73 | final List resourceLinks = mergeResources( 74 | first, 75 | second 76 | ); 77 | // then 78 | assertEquals(resourceLinks, asList(STOREFRONT_LINK, ABOUTPAGE_LINK, SHOPPAGES_LINK, FOO_LINK)); 79 | assertEquals(first.size(), 2); 80 | assertEquals(second.size(), 2); 81 | } 82 | 83 | @Test 84 | public void mergingEmptyListWithLinksShouldResultInLinks() throws Exception { 85 | // when 86 | final List resourceLinks = mergeResources( 87 | asList(STOREFRONT_LINK), 88 | Collections.emptyList() 89 | ); 90 | // then 91 | assertEquals(resourceLinks, asList(STOREFRONT_LINK)); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /jsonhome-spring/src/test/java/de/otto/jsonhome/generator/SpringHintsGeneratorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import de.otto.jsonhome.model.Hints; 20 | import org.testng.annotations.Test; 21 | 22 | import java.net.URI; 23 | 24 | import static de.otto.jsonhome.fixtures.ControllerFixtures.ControllerWithDifferentProducesAndConsumes; 25 | import static de.otto.jsonhome.fixtures.ControllerFixtures.ControllerWithHints; 26 | import static de.otto.jsonhome.model.Authentication.authReq; 27 | import static de.otto.jsonhome.model.Precondition.ETAG; 28 | import static de.otto.jsonhome.model.Precondition.LAST_MODIFIED; 29 | import static java.net.URI.create; 30 | import static java.util.Arrays.asList; 31 | import static org.testng.Assert.assertEquals; 32 | 33 | /** 34 | * @author Guido Steinacker 35 | * @since 20.10.12 36 | */ 37 | public class SpringHintsGeneratorTest { 38 | 39 | public static final URI RELATION_TYPE_BASE_URI = create("http://example.org/"); 40 | 41 | @Test 42 | public void testMethodWithTwoRepresentations() throws Exception { 43 | // given 44 | final SpringHintsGenerator generator = new SpringHintsGenerator(RELATION_TYPE_BASE_URI, null); 45 | final Class controller = ControllerWithDifferentProducesAndConsumes.class; 46 | // when 47 | final Hints hints = generator.hintsOf( 48 | create("/rel/product/form"), 49 | controller.getMethod("postSomething", String.class)); 50 | // then 51 | assertEquals(hints.getRepresentations(), asList("text/html")); 52 | assertEquals(hints.getAcceptPost(), asList("application/x-www-form-urlencoded")); 53 | } 54 | 55 | @Test 56 | public void shouldFindRequiredPrecondition() throws NoSuchMethodException { 57 | // given 58 | final SpringHintsGenerator generator = new SpringHintsGenerator(RELATION_TYPE_BASE_URI, null); 59 | final Class controller = ControllerWithHints.class; 60 | // when 61 | final Hints hints = generator.hintsOf( 62 | create("/rel/bar"), 63 | controller.getMethod("methodWithPreconditionsRequired")); 64 | // then 65 | assertEquals(hints.getPreconditionReq(), asList(ETAG, LAST_MODIFIED)); 66 | } 67 | 68 | @Test 69 | public void shouldFindRequiredAuthentication() throws NoSuchMethodException { 70 | // given 71 | final SpringHintsGenerator generator = new SpringHintsGenerator(RELATION_TYPE_BASE_URI, null); 72 | final Class controller = ControllerWithHints.class; 73 | // when 74 | final Hints hints = generator.hintsOf( 75 | create("/rel/bar"), 76 | controller.getMethod("methodWithAuthRequired")); 77 | // then 78 | assertEquals(hints.getAuthReq(), asList(authReq("Basic", asList("foo")), authReq("Digest", asList("bar")))); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /jsonhome-jersey/src/main/java/de/otto/jsonhome/generator/JerseyResourceLinkGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Guido Steinacker 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.otto.jsonhome.generator; 18 | 19 | import com.sun.jersey.api.uri.UriBuilderImpl; 20 | 21 | import javax.ws.rs.Path; 22 | import javax.ws.rs.core.UriBuilder; 23 | import java.io.UnsupportedEncodingException; 24 | import java.lang.annotation.Annotation; 25 | import java.lang.reflect.Method; 26 | import java.net.URI; 27 | import java.net.URLDecoder; 28 | 29 | /** 30 | * @author Sebastian Schroeder 31 | * @since 09.12.2012 32 | */ 33 | public final class JerseyResourceLinkGenerator extends ResourceLinkGenerator { 34 | 35 | private final URI applicationBaseUri; 36 | 37 | public JerseyResourceLinkGenerator(final URI applicationBaseUri, 38 | final URI relationTypeBaseUri, 39 | final URI varTypeBaseUri, 40 | final String docRootDir) { 41 | super(applicationBaseUri, 42 | relationTypeBaseUri, 43 | varTypeBaseUri, 44 | new JerseyHintsGenerator(relationTypeBaseUri, docRootDir), 45 | new JerseyHrefVarsGenerator(relationTypeBaseUri, docRootDir)); 46 | this.applicationBaseUri = applicationBaseUri; 47 | } 48 | 49 | /** 50 | * Returns true if the method is a candidate for further processing, false otherwise. 51 | * 52 | * @param method the method to check 53 | * @return boolean 54 | */ 55 | @Override 56 | protected boolean isCandidateForAnalysis(final Method method) { 57 | for (final Annotation annotation : method.getDeclaredAnnotations()) { 58 | if (HttpMethods.isHttpMethod(annotation)) { 59 | return true; 60 | } 61 | } 62 | return false; 63 | } 64 | 65 | /** 66 | * Returns the resource paths for the given method. 67 | * 68 | * The resource paths are the paths of the URIs the given method is responsible for. 69 | * 70 | * @param method the method of the controller, possibly handling one or more REST resources. 71 | * @return resource path 72 | */ 73 | @Override 74 | protected String resourcePathFor(final Method method) { 75 | if (isCandidateForAnalysis(method)) { 76 | final UriBuilder uriBuilder = new UriBuilderImpl() 77 | .uri(applicationBaseUri) 78 | .path(method.getDeclaringClass()); 79 | if (method.getAnnotation(Path.class) != null) { 80 | uriBuilder.path(method); 81 | } 82 | try { 83 | return URLDecoder.decode(uriBuilder.build().toString(), "UTF-8") + queryTemplateFrom(method); 84 | } catch (UnsupportedEncodingException e) { 85 | //UTF-8 should be known 86 | } 87 | } 88 | return null; 89 | } 90 | 91 | } 92 | --------------------------------------------------------------------------------