All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mockrunner.connector.MappedRecordInteraction Maven / Gradle / Ivy

There is a newer version: 2.0.7
Show newest version
package com.mockrunner.connector;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.resource.ResourceException;
import javax.resource.cci.InteractionSpec;
import javax.resource.cci.MappedRecord;
import javax.resource.cci.Record;

import com.mockrunner.base.NestedApplicationException;
import com.mockrunner.mock.connector.cci.MockMappedRecord;

/**
 * This interaction implementor works with mapped records. It takes a Map for 
 * the request and a Map or a Record instance for the response. 
 * If the request Map is null, which is the default, 
 * the implementor accepts any request and returns the specified result. If a request 
 * Map is specified,  this implementor accepts only requests that contain the same
 * data as the specified expected request Map. The underlying maps are compared
 * as described in the Map.equals method.
 * If a request is accepted, this implementor replies with the specified
 * response. You can use the various constructors and set methods
 * to configure the expected request and the response.
* Please check out the documentation of the various methods for details. */ public class MappedRecordInteraction implements InteractionImplementor { private boolean enabled; private Map expectedRequest; private Map responseData; private Class responseClass; private Record responseRecord; /** * Sets the expected request and the response to null, * i.e. an empty response is returned for every request. */ public MappedRecordInteraction() { this(null, null, MockMappedRecord.class); } /** * Sets the expected request to null and prepares * the specified response Map. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the default {@link com.mockrunner.mock.connector.cci.MockMappedRecord}. * It is allowed to pass null for the response Map * which is equivalent to an empty response. * The specified response is returned for every request. * @param responseMap the response Map */ public MappedRecordInteraction(Map responseMap) { this(null, responseMap, MockMappedRecord.class); } /** * Sets the specified expected request Map and prepares * the specified response Map. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the default {@link com.mockrunner.mock.connector.cci.MockMappedRecord}. * It is allowed to pass null for the request and response Map * which is equivalent to an empty expected request (i.e. every request is accepted) * or to an empty response respectively. * The specified response is returned, if the actual request matches the specified expected * request. * @param expectedRequest the expected request Map * @param responseMap the response Map */ public MappedRecordInteraction(Map expectedRequest, Map responseMap) { this(expectedRequest, responseMap, MockMappedRecord.class); } /** * Sets the expected request to null and prepares * the specified response Map. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the specified responseClass. The specified * responseClass must implement MappedRecord, * otherwise an IllegalArgumentException will be thrown. * It is allowed to pass null for the response Map * which is equivalent to an empty response. * The specified response is returned for every request. * @param responseMap the response MapRecord
class * @throws IllegalArgumentException if the responseClass * is not valid */ public MappedRecordInteraction(Map responseMap, Class responseClass) { this(null, responseMap, responseClass); } /** * Sets the specified expected request Map and prepares * the specified response Map. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the specified responseClass. The specified * responseClass must implement MappedRecord, * otherwise an IllegalArgumentException will be thrown. * It is allowed to pass null for the request and response Map * which is equivalent to an empty expected request (i.e. every request is accepted) * or to an empty response respectively. * The specified response is returned, if the actual request matches the specified expected * request. * @param expectedRequest the expected request Map * @param responseMap the response MapRecord class * @throws IllegalArgumentException if the responseClass * is not valid */ public MappedRecordInteraction(Map expectedRequest, Map responseMap, Class responseClass) { setExpectedRequest(expectedRequest); setResponse(responseMap, responseClass); this.enabled = true; } /** * Sets the specified expected request Map and the response * Record for the {@link #execute(InteractionSpec, Record)} * method. The response Record is ignored for * {@link #execute(InteractionSpec,Record,Record)} but takes precedence * over the specified response Map for {@link #execute(InteractionSpec, Record)}. * It is allowed to pass null for the request and response Record * which is equivalent to an empty expected request (i.e. every request is accepted) * or to no specified response Record, i.e. the specified response * Map is taken. * The specified response is returned, if the actual request matches the specified expected * request. * @param expectedRequest the expected request Map * @param responseRecord the response Record */ public MappedRecordInteraction(Map expectedRequest, Record responseRecord) { setExpectedRequest(expectedRequest); setResponse(responseRecord); this.enabled = true; } /** * Sets the expected request to null and prepares the response * Record for the {@link #execute(InteractionSpec, Record)} * method. The response Record is ignored for * {@link #execute(InteractionSpec,Record,Record)} but takes precedence * over the specified response Map for {@link #execute(InteractionSpec, Record)}. * It is allowed to pass null for the response Record * which is equivalent to no specified response Record, i.e. the specified response * Map is taken. * The specified response is returned for every request. * @param responseRecord the response Record */ public MappedRecordInteraction(Record responseRecord) { this(null, responseRecord); } /** * Enables this implementor. */ public void enable() { this.enabled = true; } /** * Disables this implementor. {@link #canHandle(InteractionSpec, Record, Record)} * always returns false, if this implementor is disabled. */ public void disable() { this.enabled = false; } /** * Sets the specified expected request Map. The response is returned, * if the actual request matches the specified expected request Map * according to Map.equals. * It is allowed to pass null for the request Map * which is equivalent to an empty expected request (i.e. every request * is accepted). * @param expectedRequest the expected request Map */ public void setExpectedRequest(Map expectedRequest) { if(null == expectedRequest) { this.expectedRequest = null; } else { this.expectedRequest = new HashMap(expectedRequest); } } /** * Prepares the specified response Map. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the default {@link com.mockrunner.mock.connector.cci.MockMappedRecord}. * It is allowed to pass null for the response Map * which is equivalent to an empty response. * @param responseMap the response MapMap. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the specified responseClass. The specified * responseClass must implement MappedRecord, * otherwise an IllegalArgumentException will be thrown. * It is allowed to pass null for the response Map * which is equivalent to an empty response. * @param responseMap the response Map * @param responseClass the response Record class * @throws IllegalArgumentException if the responseClass * is not valid */ public void setResponse(Map responseMap, Class responseClass) { if(!isResponseClassAcceptable(responseClass)) { throw new IllegalArgumentException("responseClass must implement " + MappedRecord.class.getName()); } if(null == responseMap) { this.responseData = null; } else { this.responseData = new HashMap(responseMap); } this.responseClass = responseClass; } /** * Prepares the response Record for the * {@link #execute(InteractionSpec, Record)} method. The response * Record is ignored for {@link #execute(InteractionSpec,Record,Record)} * but takes precedence over the specified response Map for * {@link #execute(InteractionSpec, Record)}. * It is allowed to pass null for the response Record * which is equivalent to no specified response Record, i.e. the specified response * Map is taken. * @param responseRecord the response Record */ public void setResponse(Record responseRecord) { this.responseRecord = responseRecord; } /** * Returns true if this implementor is enabled and will handle the request. * This method returns true if the following prerequisites are fulfilled:

* It is enabled.

* The response Record must implement MappedRecord * or it must be null (which is the case, if the actual request * targets the {@link #execute(InteractionSpec,Record)} method instead of * {@link #execute(InteractionSpec,Record,Record)}).

* The expected request must be null (use the various * setExpectedRequest methods) or the actual request Record * must implement MappedRecord and must contain the same data as * the specified expected request Map according to Map.equals.

* Otherwise, false is returned. * @param interactionSpec the InteractionSpec for the actual call * @param actualRequest the request for the actual call * @param actualResponse the response for the actual call, may be null * @return true if this implementor will handle the request and * will return the specified response, false otherwise */ public boolean canHandle(InteractionSpec interactionSpec, Record actualRequest, Record actualResponse) { if(!enabled) return false; if(!isResponseAcceptable(actualResponse)) return false; return doesRequestMatch(actualRequest); } private boolean doesRequestMatch(Record request) { if(null == expectedRequest) return true; if(null == request) return false; if(request instanceof MappedRecord) { try { MappedRecord mappedRequest = (MappedRecord)request; if(mappedRequest.size() != expectedRequest.size()) return false; Iterator keys = mappedRequest.keySet().iterator(); while(keys.hasNext()) { Object nextKey = keys.next(); Object actualValue = mappedRequest.get(nextKey); Object expectedValue = expectedRequest.get(nextKey); if(!areObjectsEquals(actualValue, expectedValue)) { return false; } } return true; } catch(Exception exc) { throw new NestedApplicationException(exc); } } return false; } private boolean areObjectsEquals(Object object1, Object object2) { if(null == object1 && null == object2) return true; if(null == object1) return false; return object1.equals(object2); } private boolean isResponseAcceptable(Record response) { return (null == response) || (response instanceof MappedRecord); } private boolean isResponseClassAcceptable(Class responseClass) { return (null == responseClass) || (MappedRecord.class.isAssignableFrom(responseClass)); } /** * First version of the execute methods.

* This method returns null, if the request does not match * according to the contract of {@link #canHandle}. This never happens under * normal conditions since the {@link InteractionHandler} does not call * execute, if {@link #canHandle} returns false. *

* Otherwise, this method returns the specified response. If a response * Record object is specified (use {@link #setResponse(Record)}), * it always takes precedence, i.e. the response Map will be ignored. * If no Record object is specified, a Record object * is created and filled with the specified response Map data. Use the * setResponse methods that take a Map * to prepare the response Map. The created Record is of the the * specified type (the setResponse method that takes a second * Class parameter allows for specifying a type). If no type * is specified, a {@link com.mockrunner.mock.connector.cci.MockMappedRecord} * is created. If no response Map is specified at all, an empty * {@link com.mockrunner.mock.connector.cci.MockMappedRecord} * will be returned. * @param interactionSpec the interaction spec * @param actualRequest the actual request * @return the response according to the current request */ public Record execute(InteractionSpec interactionSpec, Record actualRequest) throws ResourceException { if(!canHandle(interactionSpec, actualRequest, null)) return null; if(null != responseRecord) return responseRecord; MappedRecord response = null; try { if(null == responseClass) { response = new MockMappedRecord(); } else { response = (MappedRecord)responseClass.newInstance(); } if(null != responseData) { response.putAll(responseData); } } catch(Exception exc) { ResourceException resExc = new ResourceException("execute() failed"); resExc.setLinkedException(exc); throw resExc; } return (Record)response; } /** * Second version of the execute methods.

* This method returns false, if the request does not match * according to the contract of {@link #canHandle}. This never happens under * normal conditions since the {@link InteractionHandler} does not call * execute, if {@link #canHandle} returns false. *

* Otherwise, this method fills the response Record with the * specified response Map data. Use the setResponse methods that * take a Map to prepare the response Map. * The response Record must implement MappedRecord * (it does, otherwise the request would have been rejected by * {@link #canHandle}). If no response Map is specified at all, * the response Record is not touched but true * is returned anyway * @param interactionSpec the interaction spec * @param actualRequest the actual request * @param actualResponse the actual response * @return true under normal conditions */ public boolean execute(InteractionSpec interactionSpec, Record actualRequest, Record actualResponse) throws ResourceException { if(!canHandle(interactionSpec, actualRequest, actualResponse)) return false; try { if(null != responseData && null != actualResponse) { ((MappedRecord)actualResponse).clear(); ((MappedRecord)actualResponse).putAll(responseData); } } catch(Exception exc) { ResourceException resExc = new ResourceException("execute() failed"); resExc.setLinkedException(exc); throw resExc; } return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy