Improve the extensibility of the descriptor classes

This commit improves the extensibility of the various descriptor
classes. The following changes have been made:

 - Constructors have been made protected to allow them to be called by
   subclasses in a different package
 - Model creation has been moved to the relevant snippet class. This
   improves the separation of concerns as a descriptor should not be
   aware of template-based rendering and the need for a model. The
   method is protected to allow it to be overridden by a custom subclass
   that uses a custom descriptor subclass.
 - Methods that should not be overridden have been made final.

See gh-73
This commit is contained in:
Andy Wilkinson
2015-09-08 14:49:51 +01:00
parent cbbdbcb201
commit 94d5e2d94f
7 changed files with 129 additions and 57 deletions

View File

@@ -16,9 +16,6 @@
package org.springframework.restdocs.hypermedia;
import java.util.HashMap;
import java.util.Map;
import org.springframework.restdocs.snippet.AbstractDescriptor;
/**
@@ -36,7 +33,12 @@ public class LinkDescriptor extends AbstractDescriptor<LinkDescriptor> {
private boolean optional;
LinkDescriptor(String rel) {
/**
* Creates a new {@code LinkDescriptor} describing a link with the given {@code rel}.
*
* @param rel the rel of the link
*/
protected LinkDescriptor(String rel) {
this.rel = rel;
}
@@ -46,7 +48,7 @@ public class LinkDescriptor extends AbstractDescriptor<LinkDescriptor> {
* @param description The link's description
* @return {@code this}
*/
public LinkDescriptor description(String description) {
public final LinkDescriptor description(String description) {
this.description = description;
return this;
}
@@ -56,29 +58,36 @@ public class LinkDescriptor extends AbstractDescriptor<LinkDescriptor> {
*
* @return {@code this}
*/
public LinkDescriptor optional() {
public final LinkDescriptor optional() {
this.optional = true;
return this;
}
String getRel() {
/**
* Returns the rel of the link described by this descriptor
*
* @return the rel
*/
public final String getRel() {
return this.rel;
}
String getDescription() {
/**
* Returns the description for the link
*
* @return the link description
*/
public final String getDescription() {
return this.description;
}
boolean isOptional() {
/**
* Returns {@code true} if the described link is optional, otherwise {@code false}
*
* @return {@code true} if the described link is optional, otherwise {@code false}
*/
public final boolean isOptional() {
return this.optional;
}
Map<String, Object> toModel() {
Map<String, Object> model = new HashMap<>();
model.put("rel", this.rel);
model.put("description", this.description);
model.put("optional", this.optional);
model.putAll(getAttributes());
return model;
}
}

View File

@@ -131,7 +131,7 @@ public class LinksSnippet extends TemplatedSnippet {
private List<Map<String, Object>> createLinksModel() {
List<Map<String, Object>> model = new ArrayList<>();
for (Entry<String, LinkDescriptor> entry : this.descriptorsByRel.entrySet()) {
model.add(entry.getValue().toModel());
model.add(createModelForDescriptor(entry.getValue()));
}
return model;
}
@@ -146,4 +146,19 @@ public class LinksSnippet extends TemplatedSnippet {
return this.descriptorsByRel;
}
/**
* Returns a model for the given {@code descriptor}
*
* @param descriptor the descriptor
* @return the model
*/
protected Map<String, Object> createModelForDescriptor(LinkDescriptor descriptor) {
Map<String, Object> model = new HashMap<>();
model.put("rel", descriptor.getRel());
model.put("description", descriptor.getDescription());
model.put("optional", descriptor.isOptional());
model.putAll(descriptor.getAttributes());
return model;
}
}

View File

@@ -77,7 +77,7 @@ public abstract class AbstractFieldsSnippet extends TemplatedSnippet {
List<Map<String, Object>> fields = new ArrayList<>();
model.put("fields", fields);
for (FieldDescriptor descriptor : this.fieldDescriptors) {
fields.add(descriptor.toModel());
fields.add(createModelForDescriptor(descriptor));
}
return model;
}
@@ -156,4 +156,20 @@ public abstract class AbstractFieldsSnippet extends TemplatedSnippet {
return this.fieldDescriptors;
}
/**
* Returns a model for the given {@code descriptor}
*
* @param descriptor the descriptor
* @return the model
*/
protected Map<String, Object> createModelForDescriptor(FieldDescriptor descriptor) {
Map<String, Object> model = new HashMap<String, Object>();
model.put("path", descriptor.getPath());
model.put("type", descriptor.getType().toString());
model.put("description", descriptor.getDescription());
model.put("optional", descriptor.isOptional());
model.putAll(descriptor.getAttributes());
return model;
}
}

View File

@@ -16,9 +16,6 @@
package org.springframework.restdocs.payload;
import java.util.HashMap;
import java.util.Map;
import org.springframework.restdocs.snippet.AbstractDescriptor;
/**
@@ -39,7 +36,12 @@ public class FieldDescriptor extends AbstractDescriptor<FieldDescriptor> {
private String description;
FieldDescriptor(String path) {
/**
* Creates a new {@code FieldDescriptor} describing the field with the given
* {@code path}.
* @param path the path
*/
protected FieldDescriptor(String path) {
this.path = path;
}
@@ -51,7 +53,7 @@ public class FieldDescriptor extends AbstractDescriptor<FieldDescriptor> {
* @return {@code this}
* @see JsonFieldType
*/
public FieldDescriptor type(Object type) {
public final FieldDescriptor type(Object type) {
this.type = type;
return this;
}
@@ -61,7 +63,7 @@ public class FieldDescriptor extends AbstractDescriptor<FieldDescriptor> {
*
* @return {@code this}
*/
public FieldDescriptor optional() {
public final FieldDescriptor optional() {
this.optional = true;
return this;
}
@@ -72,34 +74,45 @@ public class FieldDescriptor extends AbstractDescriptor<FieldDescriptor> {
* @param description The field's description
* @return {@code this}
*/
public FieldDescriptor description(String description) {
public final FieldDescriptor description(String description) {
this.description = description;
return this;
}
String getPath() {
/**
* Returns the path of the field described by this descriptor
*
* @return the path
*/
public final String getPath() {
return this.path;
}
Object getType() {
/**
* Returns the type of the field described by this descriptor
*
* @return the type
*/
public final Object getType() {
return this.type;
}
boolean isOptional() {
/**
* Returns {@code true} if the described field is optional, otherwise {@code false}
*
* @return {@code true} if the described field is optional, otherwise {@code false}
*/
public final boolean isOptional() {
return this.optional;
}
String getDescription() {
/**
* Returns the description for the field
*
* @return the field description
*/
public final String getDescription() {
return this.description;
}
Map<String, Object> toModel() {
Map<String, Object> model = new HashMap<String, Object>();
model.put("path", this.path);
model.put("type", this.type.toString());
model.put("description", this.description);
model.put("optional", this.optional);
model.putAll(this.getAttributes());
return model;
}
}

View File

@@ -67,7 +67,7 @@ public abstract class AbstractParametersSnippet extends TemplatedSnippet {
Map<String, Object> model = new HashMap<>();
List<Map<String, Object>> parameters = new ArrayList<>();
for (Entry<String, ParameterDescriptor> entry : this.descriptorsByName.entrySet()) {
parameters.add(entry.getValue().toModel());
parameters.add(createModelForDescriptor(entry.getValue()));
}
model.put("parameters", parameters);
return model;
@@ -105,4 +105,18 @@ public abstract class AbstractParametersSnippet extends TemplatedSnippet {
return this.descriptorsByName;
}
/**
* Returns a model for the given {@link descriptor}.
*
* @param descriptor the descriptor
* @return the model
*/
protected Map<String, Object> createModelForDescriptor(ParameterDescriptor descriptor) {
Map<String, Object> model = new HashMap<>();
model.put("name", descriptor.getName());
model.put("description", descriptor.getDescription());
model.putAll(descriptor.getAttributes());
return model;
}
}

View File

@@ -16,9 +16,6 @@
package org.springframework.restdocs.request;
import java.util.HashMap;
import java.util.Map;
import org.springframework.restdocs.snippet.AbstractDescriptor;
/**
@@ -34,7 +31,13 @@ public class ParameterDescriptor extends AbstractDescriptor<ParameterDescriptor>
private String description;
ParameterDescriptor(String name) {
/**
* Creates a new {@code ParameterDescriptor} describing the parameter with the given
* {@code name}.
*
* @param name the name of the parameter
*/
protected ParameterDescriptor(String name) {
this.name = name;
}
@@ -44,25 +47,27 @@ public class ParameterDescriptor extends AbstractDescriptor<ParameterDescriptor>
* @param description The parameter's description
* @return {@code this}
*/
public ParameterDescriptor description(String description) {
public final ParameterDescriptor description(String description) {
this.description = description;
return this;
}
String getName() {
/**
* Returns the name of the parameter being described by this descriptor
*
* @return the name of the parameter
*/
public final String getName() {
return this.name;
}
String getDescription() {
/**
* Returns the description of the parameter
*
* @return the description
*/
public final String getDescription() {
return this.description;
}
Map<String, Object> toModel() {
Map<String, Object> model = new HashMap<>();
model.put("name", this.name);
model.put("description", this.description);
model.putAll(getAttributes());
return model;
}
}

View File

@@ -34,7 +34,7 @@ public abstract class AbstractDescriptor<T extends AbstractDescriptor<T>> {
private Map<String, Object> attributes = new HashMap<>();
/**
* Sets the descriptor's attributes
* Adds the given {@code attributes} to the descriptor
*
* @param attributes the attributes
* @return the descriptor
@@ -52,7 +52,7 @@ public abstract class AbstractDescriptor<T extends AbstractDescriptor<T>> {
*
* @return the attributes
*/
protected Map<String, Object> getAttributes() {
public final Map<String, Object> getAttributes() {
return this.attributes;
}