Javadoc updates.

This commit is contained in:
Jon Brisbin
2012-05-03 11:35:05 -05:00
parent ab7b497d72
commit 61170d8b43
18 changed files with 203 additions and 63 deletions

View File

@@ -11,7 +11,6 @@ allprojects {
exclude group: "commons-logging"
exclude module: "slf4j-log4j12"
exclude module: "groovy-all", version: "1.8.0-beta-3-SNAPSHOT"
resolutionStrategy.cacheChangingModulesFor(0, "seconds")
}
repositories {

View File

@@ -22,4 +22,4 @@ spockVersion = 0.5-groovy-1.8
spring.range = "[3.1.1, 4.0.0)"
jackson.range = "[1.9, 2.0.0)"
sdRestVersion = 1.0.0.BUILD-SNAPSHOT
sdRestVersion = 1.0.0.BUILD-SNAPSHOT

View File

@@ -1,8 +1,18 @@
package org.springframework.data.rest.core;
/**
* Generic interface used as a callback in any place you need extensibility.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public interface Handler<T,V> {
public interface Handler<T, V> {
/**
* Accept an argument and possibly produce a result.
*
* @param t arg
* @return Some object or {@literal null} if no result.
*/
V handle(T t);
}

View File

@@ -3,12 +3,24 @@ package org.springframework.data.rest.core;
import java.net.URI;
/**
* A simple bean representing a URI link.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public interface Link {
/**
* The text used in the {@literal rel} attribute.
*
* @return {@literal rel} attribute text.
*/
String rel();
/**
* The {@link URI} this link is referencing.
*
* @return {@link URI} of this link. Should not be null.
*/
URI href();
}

View File

@@ -3,6 +3,8 @@ package org.springframework.data.rest.core;
import java.net.URI;
/**
* Implementation of {@link Link}.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class SimpleLink implements Link {

View File

@@ -13,6 +13,9 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.util.ClassUtils;
/**
* A "fluent" bean is one that does not use the JavaBean conventions of "setProperty" and "getProperty" but instead
* uses just "property" with 0 or 1 arguments to distinguish between getter (0 arg) and setter (1 arg).
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class FluentBeanDeserializer extends StdDeserializer {

View File

@@ -1,9 +1,7 @@
package org.springframework.data.rest.core.util;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.JsonGenerationException;
@@ -13,6 +11,9 @@ import org.codehaus.jackson.map.ser.std.SerializerBase;
import org.springframework.util.ClassUtils;
/**
* A "fluent" bean is one that does not use the JavaBean conventions of "setProperty" and "getProperty" but instead
* uses just "property" with 0 or 1 arguments to distinguish between getter (0 arg) and setter (1 arg).
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class FluentBeanSerializer extends SerializerBase {

View File

@@ -16,6 +16,8 @@ import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
/**
* Helper methods for dealing with the metadata of "fluent" beans.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public abstract class FluentBeanUtils {
@@ -53,6 +55,12 @@ public abstract class FluentBeanUtils {
}
);
/**
* Interrogate a bean and collect {@link Metadata} on it.
*
* @param targetType The type to interrogate.
* @return {@link Metadata} for the fluent bean.
*/
public static Metadata metadata(Class<?> targetType) {
try {
return metadata.get(targetType);
@@ -61,6 +69,15 @@ public abstract class FluentBeanUtils {
}
}
/**
* Set the property of a fluent bean.
*
* @param property Name of the property to set.
* @param value Value of the property.
* @param bean Bean on which to set this property.
* @return Usually {@literal null} but will return whatever the "setter" returns, which could be {@this} or something
* else.
*/
public static Object set(String property, Object value, Object bean) {
if (null == bean) {
return null;
@@ -82,6 +99,13 @@ public abstract class FluentBeanUtils {
}
}
/**
* Get the value of a property.
*
* @param property Name of the property.
* @param bean Bean of which to get the property.
* @return Value of the property. Could be {@literal null}
*/
public static Object get(String property, Object bean) {
if (null == bean) {
return null;
@@ -103,6 +127,14 @@ public abstract class FluentBeanUtils {
}
}
/**
* Determines whether a given type looks like a fluent bean. That means it has methods whose names exactly correspond
* to a field of the same name. A "getter" is that method which is named the same as the field and has 0 parameters.
* The "setter" is that method which is named the same as the field and has a single argument.
*
* @param type The class to inspect.
* @return {@literal true} if this looks like a fluent bean, {@literal false} otherwise.
*/
public static boolean isFluentBean(Class<?> type) {
try {
return metadata.get(type).getters.size() > 0;

View File

@@ -9,6 +9,8 @@ import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;
/**
* Helper methods for dealing with URIs.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public abstract class UriUtils {
@@ -16,11 +18,35 @@ public abstract class UriUtils {
private UriUtils() {
}
/**
* Is the given {@link URI} based on the "base" {@link URI}?
* <p>e.g. given a base URI of {@literal http://localhost:8080/data} and a URI of {@code
* http://localhost:8080/data/person}, this method would report the baseUri being a valid base of the given URI.
* </p>
*
* @param baseUri {@link URI} to check.
* @param uri {@link URI} against which to compare the base.
* @return {@literal true} if the baseUri is valid against the given {@link URI}, {@literal false} otherwise.
*/
public static boolean validBaseUri(URI baseUri, URI uri) {
String path = UriUtils.path(baseUri.relativize(uri));
return !StringUtils.hasText(path) || path.charAt(0) != '/';
}
/**
* Execute the given {@link Handler} for each segment in the {@link URI}.
* <p>e.g. given a URI of {@literal http://localhost:8080/data/person/1} and a base URI of {@code
* http://localhost:8080/data}, this method will explode the URI into it's components, as compared to the base URI.
* The result would be: the given handler gets called twice, once passing a relative {@link URI} of "person" and a
* second time passing a relative {@link URI} of "1".
* </p>
*
* @param baseUri base {@link URI}
* @param uri {@link URI} to explode and iteratre over.
* @param handler {@link Handler} to call for each segment of the URI's path.
* @param <V> Return type of the handler.
* @return Handler return value, or possibly {@literal null}.
*/
public static <V> V foreach(URI baseUri, URI uri, Handler<URI, V> handler) {
List<URI> uris = explode(baseUri, uri);
V v = null;
@@ -30,6 +56,17 @@ public abstract class UriUtils {
return v;
}
/**
* Explode the given {@link URI} into its component parts, as compared to the base {@link URI}.
* <p>Given a base URI of {@literal http://localhost:8080/data}, exploding the URI {@code
* http://localhost:8080/data/person/1} strips the first part of the URI, leaving {@literal person/1}. This results
* in
* a {@link Stack} of relative {@link URI}s of size 2--one for "person" and one for "1".</p>
*
* @param baseUri base {@link URI}
* @param uri {@link URI} to explode
* @return {@link Stack} of relative {@link URI}s.
*/
public static Stack<URI> explode(URI baseUri, URI uri) {
Stack<URI> uris = new Stack<URI>();
if (StringUtils.hasText(uri.getPath())) {
@@ -43,6 +80,16 @@ public abstract class UriUtils {
return uris;
}
/**
* Merge the components of these {@link URI}s into a single URI. Useful for combining a relative URI with a base URI
* and coming up with a full absolute URI.
* <p>e.g. merging base URI {@literal http://localhost:8080/data} and relative uri {@literal person/1?name=John+Doe}
* would result in an absolute URI of {@literal http://localhost:8080/data/person/1?name=John+Doe}</p>
*
* @param baseUri base {@link URI}
* @param uris {@link URI}s to merge
* @return {@link URI} that is the combination of all the given (possibly relative, possibly absolute) URIs.
*/
public static URI merge(URI baseUri, URI... uris) {
StringBuilder query = new StringBuilder();
@@ -98,6 +145,12 @@ public abstract class UriUtils {
return ub.build().toUri();
}
/**
* Just the path portion of the {@link URI}, but with any trailing slash "/" removed.
*
* @param uri
* @return
*/
public static String path(URI uri) {
if (null == uri) {
return null;
@@ -110,6 +163,13 @@ public abstract class UriUtils {
}
}
/**
* The very last segment of the {@link URI}.
*
* @param baseUri base {@link URI}
* @param uri {@link URI} to explode
* @return Relative {@link URI} that is the last segment of the path for the given URI.
*/
public static URI tail(URI baseUri, URI uri) {
Stack<URI> uris = explode(baseUri, uri);
return uris.size() > 0 ? uris.get(Math.max(uris.size() - 1, 0)) : null;

View File

@@ -14,83 +14,83 @@ public interface AttributeMetadata {
/**
* Name of the attribute.
*
* @return
* @return name of the attribute.
*/
String name();
/**
* The type of this attribute.
*
* @return
* @return type of this attribute.
*/
Class<?> type();
/**
* The element type of this attribute, if this attribute is a "plural"-like attribute (a Collection, Map, etc...).
*
* @return
* @return Class of element type or {@literal null} if not a plural attribute.
*/
Class<?> elementType();
/**
* Can this attribute look like a {@link Collection}?
*
* @return
* @return {@literal true} if attribute is a Collection, {@literal false} otherwise.
*/
boolean isCollectionLike();
/**
* Get the path of this attribute as a {@link Collection}.
*
* @param target
* @return
* @param target The entity to inspect for this attribute.
* @return attribute value as a {@link Collection}
*/
Collection<?> asCollection(Object target);
/**
* Can this attribute look like a {@link Set}?
*
* @return
* @return {@literal true} if attribute is a Set, {@literal false} otherwise.
*/
boolean isSetLike();
/**
* Get the path of this attribute as a {@link Set}.
*
* @param target
* @return
* @param target The entity to inspect for this attribute.
* @return attribute value as a {@link Set}
*/
Set<?> asSet(Object target);
/**
* Can this attribute look like a {@link Map}?
*
* @return
* @return {@literal true} if attribute is a Map, {@literal false} otherwise.
*/
boolean isMapLike();
/**
* Get the path of this attribute as a {@link Map}.
*
* @param target
* @return
* @param target The entity to inspect for this attribute.
* @return attribute value as a {@link Map}
*/
Map asMap(Object target);
/**
* Get the path of this attribute.
*
* @param target
* @return
* @param target The entity to inspect for this attribute.
* @return attribute value
*/
Object get(Object target);
/**
* Set the path of this attribute.
*
* @param value
* @param target
* @return
* @param value Value to set on this attribute.
* @param target The entity to set this attribute's value on.
* @return @this
*/
AttributeMetadata set(Object value, Object target);

View File

@@ -12,43 +12,43 @@ public interface EntityMetadata<A extends AttributeMetadata> {
/**
* The class of this entity.
*
* @return
* @return Type of this domain class.
*/
Class<?> type();
/**
* A Map of attribute metadata keyed on the attribute's name.
*
* @return
* @return Attributes that do not involve relationships.
*/
Map<String, A> embeddedAttributes();
/**
* A Map of linked attribute metadata keyed on the attribute's name.
*
* @return
* @return Attributes that involve relationships.
*/
Map<String, A> linkedAttributes();
/**
* The {@link AttributeMetadata} representing the ID of the entity.
*
* @return
* @return {@link AttributeMetadata} for the ID.
*/
A idAttribute();
/**
* The {@link AttributeMetadata} representing the version of the entity, if applicable.
*
* @return
* @return {@link AttributeMetadata} or {@literal null} if no version attributes exists.
*/
A versionAttribute();
/**
* Get {@link AttributeMetadata} by name.
*
* @param name
* @return
* @param name The name of the attribute.
* @return {@link AttributeMetadata} or {@literal null} if that attribute doesn't exist.
*/
A attribute(String name);

View File

@@ -42,7 +42,7 @@ public abstract class RepositoryExporter<M extends RepositoryMetadata<E>, E exte
* Set the class names of only those Repositories you want exported.
* Default is to export all found Repositories.
*
* @param exportOnlyTheseClasses
* @param exportOnlyTheseClasses {@link List} of class names to export.
* @return @this
*/
@SuppressWarnings({"unchecked"})
@@ -79,7 +79,7 @@ public abstract class RepositoryExporter<M extends RepositoryMetadata<E>, E exte
/**
* Get the list of Repository names being exported.
*
* @return
* @return {@link List} of class names to export.
*/
public Set<String> repositoryNames() {
return repositoryMetadata.keySet();
@@ -88,7 +88,7 @@ public abstract class RepositoryExporter<M extends RepositoryMetadata<E>, E exte
/**
* Is a Repository being exporter that supports this domain type?
*
* @param domainType
* @param domainType Type of the domain class.
* @return {@literal true} if a Repository is being exported, {@literal false} otherwise.
*/
public boolean hasRepositoryFor(Class<?> domainType) {
@@ -103,7 +103,7 @@ public abstract class RepositoryExporter<M extends RepositoryMetadata<E>, E exte
/**
* Get the RepositoryMetadata for the Repository responsible for this domain type.
*
* @param domainType
* @param domainType Type of the domain class.
* @return {@link RepositoryMetadata} instance
*/
public M repositoryMetadataFor(Class<?> domainType) {
@@ -118,7 +118,7 @@ public abstract class RepositoryExporter<M extends RepositoryMetadata<E>, E exte
/**
* Get the {@link RepositoryMetadata} for the Repository exported under the given name.
*
* @param name
* @param name Name a Repository would be exported under.
* @return {@link RepositoryMetadata} instance
*/
public M repositoryMetadataFor(String name) {

View File

@@ -18,7 +18,7 @@ public abstract class RepositoryExporterSupport<S extends RepositoryExporterSupp
/**
* Get a List of {@link RepositoryExporter}s.
*
* @return
* @return Exported {@link RepositoryExporter}s.
*/
public List<RepositoryExporter> getRepositoryExporters() {
return repositoryExporters;
@@ -27,7 +27,7 @@ public abstract class RepositoryExporterSupport<S extends RepositoryExporterSupp
/**
* Set the List of {@link RepositoryExporter}s.
*
* @param repositoryExporters
* @param repositoryExporters Export this {@link List} of {@link RepositoryExporter}s.
*/
public void setRepositoryExporters(List<RepositoryExporter> repositoryExporters) {
this.repositoryExporters = repositoryExporters;
@@ -36,7 +36,7 @@ public abstract class RepositoryExporterSupport<S extends RepositoryExporterSupp
/**
* Get a List of {@link RepositoryExporter}s.
*
* @return
* @return Exported {@link RepositoryExporter}s.
*/
public List<RepositoryExporter> repositoryExporters() {
return repositoryExporters;
@@ -45,7 +45,8 @@ public abstract class RepositoryExporterSupport<S extends RepositoryExporterSupp
/**
* Set the List of {@link RepositoryExporter}s.
*
* @param repositoryExporters
* @param repositoryExporters Export this {@link List} of {@link RepositoryExporter}s.
* @return @this
*/
@SuppressWarnings({"unchecked"})
public S repositoryExporters(List<RepositoryExporter> repositoryExporters) {
@@ -53,6 +54,13 @@ public abstract class RepositoryExporterSupport<S extends RepositoryExporterSupp
return (S) this;
}
/**
* Find {@link RepositoryMetadata} for the {@link org.springframework.data.repository.Repository} exported under this
* name.
*
* @param name URL segment name.
* @return {@link RepositoryMetadata} or {@literal null} if none found.
*/
@SuppressWarnings({"unchecked"})
protected RepositoryMetadata repositoryMetadataFor(String name) {
for (RepositoryExporter exporter : repositoryExporters) {
@@ -64,6 +72,13 @@ public abstract class RepositoryExporterSupport<S extends RepositoryExporterSupp
throw new RepositoryNotFoundException("No repository found for name " + name);
}
/**
* Find the {@link RepositoryMetadata} for the {@link org.springframework.data.repository.Repository} responsible for
* the given domain type.
*
* @param domainType Type of the domain class.
* @return {@link RepositoryMetadata} or {@literal null} if none found.
*/
@SuppressWarnings({"unchecked"})
protected RepositoryMetadata repositoryMetadataFor(Class<?> domainType) {
for (RepositoryExporter exporter : repositoryExporters) {
@@ -75,6 +90,13 @@ public abstract class RepositoryExporterSupport<S extends RepositoryExporterSupp
throw new RepositoryNotFoundException("No repository found for type " + domainType.getName());
}
/**
* Find the {@link RepositoryMetadata} for an attribute of an entity which is possibly managed by a {@link
* org.springframework.data.repository.Repository}.
*
* @param attrMeta {@link AttributeMetadata} of a possibly-managed entity.
* @return {@link RepositoryMetadata} or {@literal null} if none found.
*/
@SuppressWarnings({"unchecked"})
protected RepositoryMetadata repositoryMetadataFor(AttributeMetadata attrMeta) {
if (attrMeta.isCollectionLike() || attrMeta.isMapLike()) {

View File

@@ -16,57 +16,57 @@ public interface RepositoryMetadata<E extends EntityMetadata<? extends Attribute
/**
* The name this {@link Repository} is exported under.
*
* @return
* @return Name used in the URL for this Repository.
*/
String name();
/**
* Get the string value to be used as part of a link {@literal rel} attribute.
*
* @return
* @return Rel value used in links.
*/
String rel();
/**
* The type of domain object this {@link Repository} is repsonsible for.
*
* @return
* @return Type of the domain class.
*/
Class<?> domainType();
/**
* The Class of the {@link Repository} subinterface.
*
* @return
* @return Type of the Repository being proxied.
*/
Class<?> repositoryClass();
/**
* The {@link Repository} instance.
*
* @return
* @return The actual {@link Repository} instance.
*/
CrudRepository<Object, Serializable> repository();
/**
* The {@link EntityMetadata} associated with the domain type of this {@literal Repository}.
*
* @return
* @return EntityMetadata associated with this Repository's domain type.
*/
E entityMetadata();
/**
* Get a {@link RepositoryQueryMethod} by key.
*
* @param key
* @return
* @param key Segment of the URL to find a query method for.
* @return Found {@link RepositoryQueryMethod} or {@literal null} if none found.
*/
RepositoryQueryMethod queryMethod(String key);
/**
* Get a Map of all {@link RepositoryQueryMethod}s, keyed by name.
*
* @return
* @return All query methods for this Repository.
*/
Map<String, RepositoryQueryMethod> queryMethods();

View File

@@ -18,8 +18,6 @@ public @interface RepositoryEventHandler {
/**
* The list of {@link org.springframework.context.ApplicationEvent} classes this event handler cares about.
*
* @return
*/
Class<?>[] value() default {};

View File

@@ -55,7 +55,7 @@ public class AnnotatedHandlerRepositoryEventListener
/**
* Get the base package in which to search for event handlers.
*
* @return
* @return Base package to search.
*/
public String getBasePackage() {
return basePackage;
@@ -64,8 +64,8 @@ public class AnnotatedHandlerRepositoryEventListener
/**
* Set the base package in which to search for event handlers.
*
* @param basePackage
* @return
* @param basePackage Base package to search for handlers.
* @return @this
*/
public AnnotatedHandlerRepositoryEventListener setBasePackage(String basePackage) {
this.basePackage = basePackage;
@@ -75,7 +75,7 @@ public class AnnotatedHandlerRepositoryEventListener
/**
* Get the base package in which to search for event handlers.
*
* @return
* @return Base package to search.
*/
public String basePackage() {
return basePackage;
@@ -84,8 +84,8 @@ public class AnnotatedHandlerRepositoryEventListener
/**
* Set the base package in which to search for event handlers.
*
* @param basePackage
* @return
* @param basePackage Base package to search for handlers.
* @return @this
*/
public AnnotatedHandlerRepositoryEventListener basePackage(String basePackage) {
this.basePackage = basePackage;

View File

@@ -17,7 +17,7 @@ public abstract class LinkSaveEvent extends RepositoryEvent {
/**
* Get the linked object.
*
* @return
* @return The entity representing the right-hand side of this relationship.
*/
public Object getLinked() {
return linked;

View File

@@ -38,9 +38,9 @@ public class ValidatingRepositoryEventListener
Validator v = entry.getValue();
if (entry.getKey().contains("Save")) {
name = entry.getKey().substring(0, name.indexOf("Save") + 4);
name = entry.getKey().substring(0, entry.getKey().indexOf("Save") + 4);
} else if (entry.getKey().contains("Delete")) {
name = entry.getKey().substring(0, name.indexOf("Delete") + 6);
name = entry.getKey().substring(0, entry.getKey().indexOf("Delete") + 6);
}
if (null != name) {
this.validators.put(name, v);
@@ -52,7 +52,7 @@ public class ValidatingRepositoryEventListener
/**
* Get a Map of {@link Validator}s that are assigned to the various {@link RepositoryEvent}s.
*
* @return
* @return Validators assigned to events.
*/
public Map<String, Collection<Validator>> getValidators() {
return validators.asMap();
@@ -61,7 +61,8 @@ public class ValidatingRepositoryEventListener
/**
* Assign a Map of {@link Validator}s that are assigned to the various {@link RepositoryEvent}s.
*
* @return
* @param validators A Map of Validators to wire.
* @return @this
*/
public ValidatingRepositoryEventListener setValidators(Map<String, Collection<Validator>> validators) {
for (Map.Entry<String, Collection<Validator>> entry : validators.entrySet()) {
@@ -73,9 +74,9 @@ public class ValidatingRepositoryEventListener
/**
* Add a {@link Validator} that will be triggered on the given event.
*
* @param event
* @param validator
* @return
* @param event The event to listen for.
* @param validator The Validator to execute when that event fires.
* @return @this
*/
public ValidatingRepositoryEventListener addValidator(String event, Validator validator) {
validators.put(event, validator);