BATCH-84: Modified JobIdentifier interface to include new JobRuntimeParameters value object, and modified its subclasses accordingly.

This commit is contained in:
lucasward
2008-01-07 06:19:06 +00:00
parent e8c2539656
commit ea93f7a4c7
8 changed files with 497 additions and 56 deletions

View File

@@ -16,15 +16,15 @@
package org.springframework.batch.core.domain;
/**
* Identifier strategy for {@link JobInstance}. Different batch projects can
* have different approaches and requirements regarding the identity of a job.
* The minimum requirement is to provide a unique name to identify a job. Other
* applications or projects might add other properties like a schedule date, or
* an additional label (code).
* The minimum requirement is to provide a unique name to identify a job and JobRuntimeParameters.
*
* @author Dave Syer
*
* @author Lucas Ward
* @since 1.0
*/
public interface JobIdentifier {
@@ -34,5 +34,13 @@ public interface JobIdentifier {
* @return the name of the job
*/
public String getName();
/**
* A simple getter for the {@link JobRuntimeParameters} that also identify
* this job.
*
* @return JobRuntimeParameters
*/
public JobRuntimeParameters getRuntimeParameters();
}

View File

@@ -0,0 +1,178 @@
/**
*
*/
package org.springframework.batch.core.domain;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.springframework.util.Assert;
/**
* Value object representing runtime parameters to a batch job. Because
* the parameters have no individual meaning outside of the JobIdentifier they
* are contained within, it is a value object rather than an entity. It is also
* extremely important that a parameters object can be reliably compared to another
* for equality, in order to determine if one JobIdentifier equals another.
* Furthermore, because these parameters will need to be persisted, it is vital
* that the types added are restricted.
*
* @author Lucas Ward
* @since 1.0
*/
public class JobRuntimeParameters {
private final Map stringMap;
private final Map longMap;
private final Map dateMap;
/**
* Default constructor. Creates a new empty JobRuntimeParameters. It should be noted
* that this constructor should only be used if an empty parameters is needed, since
* JobRuntimeParameters is immutable.
*/
public JobRuntimeParameters(){
this.stringMap = new HashMap();
this.longMap = new HashMap();
this.dateMap = new HashMap();
}
/**
* Create a new parameters object based upon three maps for each of the three
* data types. See {@link JobRuntimeParametersBuilder} for an easier way to
* create paramters.
*
* @param stringMap
* @param longMap
* @param dateMap
*/
public JobRuntimeParameters(Map stringMap, Map longMap, Map dateMap){
super();
validateMap(stringMap, String.class);
validateMap(longMap, Long.class);
validateMap(dateMap, Date.class);
this.stringMap = stringMap;
this.longMap = longMap;
this.dateMap = copyDateMap(dateMap);
}
/**
* Typesafe Getter for the String represented by the provided key.
*
* @param key
* @return
*/
public String getString(String key){
return (String)stringMap.get(key);
}
/**
* Typesafe Getter for the Long represented by the provided key.
*
* @param key
* @return
*/
public Long getLong(String key){
return (Long)longMap.get(key);
}
/**
* Typesafe Getter for the Date represented by the provided key.
*
* @param key
* @return
*/
public Date getDate(String key){
return (Date)dateMap.get(key);
}
/**
* Get a map of all parameters, including string, long, and date. It should be noted
* that a Collections$UnmodifiableMap is returned, ensuring immutability.
*
* @return an unmodifiable map containing all parameters.
*/
public Map getParameters(){
Map tempMap = new HashMap(stringMap);
tempMap.putAll(longMap);
tempMap.putAll(dateMap);
return Collections.unmodifiableMap(tempMap);
}
/*
* Convenience method for validating that a the provided map only contains a particular
* type as a value, with only a String as a key.
*/
private void validateMap(Map map, Class type){
for(Iterator it = map.entrySet().iterator();it.hasNext();){
Entry entry = (Entry)it.next();
if(entry.getKey() instanceof String == false){
throw new IllegalArgumentException("All parameter keys must be strings.");
}
if(entry.getValue().getClass() != type){
throw new IllegalArgumentException("The values in this map must be of type:[" + type +
"].");
}
}
}
/*
* Convenience method for copying Date values to ensure immutability.
*/
private Map copyDateMap(Map dateMap){
Map tempMap = new HashMap();
for(Iterator it = dateMap.entrySet().iterator();it.hasNext();){
Entry entry = (Entry)it.next();
Date date = (Date)entry.getValue();
tempMap.put(entry.getKey(), new Date(date.getTime()));
}
return tempMap;
}
public boolean equals(Object obj) {
if(obj instanceof JobRuntimeParameters == false){
return false;
}
if(this == obj){
return true;
}
JobRuntimeParameters parameters = (JobRuntimeParameters)obj;
//Since the type contained by each map is known, it's safe to call Map.equals()
if(getParameters().equals(parameters.getParameters())){
return true;
}
else{
return false;
}
}
public int hashCode() {
return new HashCodeBuilder(7, 21).
append(stringMap).
append(longMap).
append(dateMap).
toHashCode();
}
public String toString() {
return stringMap.toString() + longMap.toString() + dateMap.toString();
}
}

View File

@@ -0,0 +1,88 @@
/**
*
*/
package org.springframework.batch.core.domain;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.Assert;
/**
* Helper class for creating JobRuntimeParameters. Useful because of all JobRuntimeParameters
* are immutable, and require 3 separate maps of the three supported types to ensure typesafety.
* Once created, it can be used in the same was a java.lang.StringBuilder (except, order is irrelevant),
* by adding various parameters types and creating a valid JobRuntimeParametres once finished.
*
* @author Lucas Ward
* @since 1.0
* @see JobRuntimeParameters
*/
public class JobRuntimeParametersBuilder {
private final Map stringMap;
private final Map longMap;
private final Map dateMap;
/**
* Default constructor. Initializes the builder
*/
public JobRuntimeParametersBuilder() {
this.stringMap = new HashMap();
this.longMap = new HashMap();
this.dateMap = new HashMap();
}
/**
* Add a new String parameter for the given key.
*
* @param key - parameter accessor.
* @param parameter - runtime parameter
* @return a refernece to this object.
*/
public JobRuntimeParametersBuilder addString(String key, String parameter){
Assert.notNull(parameter, "Parameter must not be null.");
stringMap.put(key, parameter);
return this;
}
/**
* Add a new Date parameter for the given key.
*
* @param key - parameter accessor.
* @param parameter - runtime parameter
* @return a refernece to this object.
*/
public JobRuntimeParametersBuilder addDate(String key, Date parameter){
Assert.notNull(parameter, "Parameter must not be null.");
dateMap.put(key, new Date(parameter.getTime()));
return this;
}
/**
* Add a new Long parameter for the given key.
*
* @param key - parameter accessor.
* @param parameter - runtime parameter
* @return a refernece to this object.
*/
public JobRuntimeParametersBuilder addLong(String key, Long parameter){
Assert.notNull(parameter, "Parameter must not be null.");
longMap.put(key, parameter);
return this;
}
/**
* Conversion method that takes the current state of this builder and returns it as
* a JobruntimeParameters object.
*
* @return a valid JobRuntimeParameters object.
*/
public JobRuntimeParameters toJobRuntimeParameters(){
return new JobRuntimeParameters(stringMap, longMap, dateMap);
}
}

View File

@@ -18,22 +18,27 @@ package org.springframework.batch.core.runtime;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.springframework.batch.core.domain.JobIdentifier;
import org.springframework.batch.core.domain.JobRuntimeParameters;
import org.springframework.util.ClassUtils;
/**
* Simple, immutable, implementation of the JobIdentifier interface.
*
* @author Dave Syer
* @author Lucas Ward
*
*/
public class SimpleJobIdentifier implements JobIdentifier {
private String name;
private JobRuntimeParameters runtimeParameters;
/**
* Default constructor.
* Default constructor. Since there it is required that the Identifier at least have a name,
* the default constructor should not be called.
*/
public SimpleJobIdentifier() {
private SimpleJobIdentifier() {
super();
}
@@ -42,8 +47,12 @@ public class SimpleJobIdentifier implements JobIdentifier {
* @param name
*/
public SimpleJobIdentifier(String name) {
super();
this(name, new JobRuntimeParameters());
}
public SimpleJobIdentifier(String name, JobRuntimeParameters runtimeParameters){
this.name = name;
this.runtimeParameters = runtimeParameters;
}
/* (non-Javadoc)
@@ -53,24 +62,33 @@ public class SimpleJobIdentifier implements JobIdentifier {
return this.name;
}
/**
* Public setter for the name.
*
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
public JobRuntimeParameters getRuntimeParameters() {
return runtimeParameters;
}
public String toString() {
return ClassUtils.getShortName(getClass())+": name=" + name;
return ClassUtils.getShortName(getClass())+": name=" + name + "parameters=" + runtimeParameters;
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
if(obj instanceof SimpleJobIdentifier == false){
return false;
}
if(this == obj){
return true;
}
SimpleJobIdentifier rhs = (SimpleJobIdentifier)obj;
return new EqualsBuilder().
append(runtimeParameters,rhs.getRuntimeParameters()).
append(name, rhs.getName()).
isEquals();
}
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
}