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

@@ -1,30 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-batch-core</name>
<comment>Core domain for batch processing, expressing a domain of Jobs, Steps, Chunks, etc.</comment>
<projects>
<project>spring-batch-infrastructure</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.springframework.ide.eclipse.core.springnature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.devzuz.q.maven.jdt.core.mavenNature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-batch-core</name>
<comment>Core domain for batch processing, expressing a domain of Jobs, Steps, Chunks, etc.</comment>
<projects>
<project>spring-batch-infrastructure</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.springframework.ide.eclipse.core.springnature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.devzuz.q.maven.jdt.core.mavenNature</nature>
</natures>
</projectDescription>

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);
}
}

View File

@@ -0,0 +1,36 @@
/**
*
*/
package org.springframework.batch.core.domain;
import java.util.Date;
import junit.framework.TestCase;
/**
* @author Lucas Ward
*
*/
public class JobRuntimeParametersBuilderTests extends TestCase {
JobRuntimeParametersBuilder parametersBuilder;
Date date = new Date(System.currentTimeMillis());
protected void setUp() throws Exception {
super.setUp();
parametersBuilder = new JobRuntimeParametersBuilder();
parametersBuilder.addDate("SCHEDULE_DATE", date);
parametersBuilder.addLong("LONG", new Long(1));
parametersBuilder.addString("STRING", "string value");
}
public void testToJobRuntimeParamters(){
JobRuntimeParameters parameters = parametersBuilder.toJobRuntimeParameters();
assertEquals(parameters.getDate("SCHEDULE_DATE"), date);
assertEquals(parameters.getLong("LONG"), new Long(1));
assertEquals(parameters.getString("STRING"), "string value");
}
}

View File

@@ -0,0 +1,122 @@
/**
*
*/
package org.springframework.batch.core.domain;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
/**
* @author Lucas Ward
*
*/
public class JobRuntimeParametersTests extends TestCase {
JobRuntimeParameters parameters;
Map stringMap;
Map longMap;
Map dateMap;
Date date1 = new Date(4321431242L);
Date date2 = new Date(7809089900L);
protected void setUp() throws Exception {
super.setUp();
parameters = getNewParameters();
}
private JobRuntimeParameters getNewParameters(){
stringMap = new HashMap();
stringMap.put("string.key1", "value1");
stringMap.put("string.key2", "value2");
longMap = new HashMap();
longMap.put("long.key1", new Long(1));
longMap.put("long.key2", new Long(2));
dateMap = new HashMap();
dateMap.put("date.key1", date1 );
dateMap.put("date.key2", date2 );
return new JobRuntimeParameters(stringMap, longMap, dateMap);
}
public void testBadLongConstructorException() throws Exception{
Map badLongMap = new HashMap();
badLongMap.put("key", "bad long");
try{
JobRuntimeParameters testParameters = new JobRuntimeParameters(stringMap, badLongMap, dateMap);
fail();
}
catch(IllegalArgumentException ex){
//expected
}
}
public void testBadStringConstructorException() throws Exception{
Map badMap = new HashMap();
badMap.put("key", new Integer(2));
try{
JobRuntimeParameters testParameters = new JobRuntimeParameters(badMap, longMap, dateMap);
fail();
}
catch(IllegalArgumentException ex){
//expected
}
}
public void testBadDateConstructorException() throws Exception{
Map badMap = new HashMap();
badMap.put("key", new java.sql.Date(System.currentTimeMillis()));
try{
JobRuntimeParameters testParameters = new JobRuntimeParameters(stringMap, longMap, badMap);
fail();
}
catch(IllegalArgumentException ex){
//expected
}
}
public void testGetString(){
assertEquals("value1", parameters.getString("string.key1"));
assertEquals("value2", parameters.getString("string.key2"));
}
public void testGetLong(){
assertEquals(new Long(1), parameters.getLong("long.key1"));
assertEquals(new Long(2), parameters.getLong("long.key2"));
}
public void testGetDate(){
assertEquals(date1, parameters.getDate("date.key1"));
assertEquals(date2, parameters.getDate("date.key2"));
}
public void testEquals(){
JobRuntimeParameters testParameters = getNewParameters();
assertTrue(testParameters.equals(parameters));
}
public void testToString(){
assertEquals("{string.key1=value1, string.key2=value2}{long.key1=1, long.key2=2}" +
"{date.key2=Wed Apr 01 03:11:29 CST 1970, date.key1=Thu Feb 19 18:23:51 CST 1970}", parameters.toString());
}
}

View File

@@ -25,13 +25,6 @@ public class SimpleJobIdentifierTests extends TestCase {
private SimpleJobIdentifier identifier = new SimpleJobIdentifier("foo");
/**
* Test method for
* {@link org.springframework.batch.core.runtime.SimpleJobIdentifier#SimpleJobIdentifier()}.
*/
public void testSimpleJobIdentifier() {
assertNull(new SimpleJobIdentifier().getName());
}
/**
* Test method for
@@ -39,8 +32,6 @@ public class SimpleJobIdentifierTests extends TestCase {
*/
public void testGetName() {
assertEquals("foo", identifier.getName());
identifier.setName("bar");
assertEquals("bar", identifier.getName());
}
/**