// // Copyright (c)1998-2011 Pearson Education, Inc. or its affiliate(s). // All rights reserved. // package openadk.library.tools.mapping; import java.util.Map; import java.util.Set; import openadk.library.*; import org.apache.commons.jxpath.Variables; /** * * A FieldAdaptor implementation that contains field values to assign to the * supplied SIFDataObject, where each entry in the map is keyed by the * local application-defined name of a field and the value is the native * Java datatype of the corresponding element or attribute of the * SIFDataObject, such as a Calender, String, Integer, Boolean, etc.<p> * * To use this class,<p> * * <ol> * <li> * Create an instance and optionally populate the Map with known field * values that will not be subject to the mapping process. If pre-loading * the Map, the key of each entry should be the local * application-defined field name and the value should be the native data type * value of that field. Any field added to the Map before calling * this method will not be subject to mapping rules, unless the * {@link openadk.library.tools.mapping.ObjectMapAdaptor#setOverwriteValues(boolean)} * property is set to <code>True</code>. * </li> * <li> * Use this class instance with the {@link openadk.library.tools.mapping.Mappings} * class,by calling the appropriate <code>map</code> method and passing the SIFDataObject * instance to retrieve field values from for insertion into the * Map. The method first looks up the ObjectMapping instance * corresponding to the SIF Data Object type. If no ObjectMapping * has been defined for the object type, no action is taken and the * method returns successfully without exception. Otherwise, all * field rules defined by the ObjectMapping are evaluated in order. * If a rule evaluates successfully, the corresponding element or * attribute value will be inserted into the HashMap. A rule will * not be evaluated if the associated field already exists in the * Map, unless the * {@link openadk.library.tools.mapping.ObjectMapAdaptor#setOverwriteValues(boolean)} * property is set to <code>True</code>. * </li> * </ol> * * @see openadk.library.tools.mapping.Mappings * * @author Andrew Elmhorst * * @version 2.0 * */ public class ObjectMapAdaptor implements FieldAdaptor, Variables { protected Map fMap; private boolean fOverwriteValues = false; /** * Creates an instance of ObjectMapAdaptor that uses the specified Map * @param map The <code>Map</code> to use for SIF Data mapping operations */ public ObjectMapAdaptor( Map map ) { fMap = map; } /** * Converts a SIF datatype value to the java native type to be stored * in the Map. The default implementation of this class stores the * native Java value, but subclasses can override this method to convert * the value to the form they want to use. * @param value The SIF value to stored in the Map * @return The converted value stored in the Map */ protected Object toMapValue( SIFSimpleType value ) { return value.getValue(); } /** * Converts the object stored in the Map to the SIF data type. The data * type required by SIF is available by examining the {@link SIFTypeConverter} * passed in to the method. * @param fieldName TODO * @param mapValue The value that was retrieved from the Map * @param typeConverter A representation of the desired SIF datatype * @return The converted SIF value */ protected SIFSimpleType fromMapValue( String fieldName, Object mapValue, SIFTypeConverter typeConverter ) { return typeConverter.getSIFSimpleType( mapValue ); } /** * @see openadk.library.tools.mapping.FieldAdaptor#getValue(java.lang.String) */ public Object getValue(String fieldName ) { return fMap.get( fieldName ); } /** * @see openadk.library.tools.mapping.FieldAdaptor#hasField(java.lang.String) */ public boolean hasField(String fieldName) { return fMap.containsKey( fieldName ); } /** * @see openadk.library.tools.mapping.FieldAdaptor#setSIFValue(java.lang.String, openadk.library.SIFSimpleType, openadk.library.tools.mapping.FieldMapping) */ public void setSIFValue(String fieldName, SIFSimpleType resultingValue, FieldMapping mapping ) { if( fOverwriteValues || !fMap.containsKey( fieldName ) ){ Object mapValue = toMapValue( resultingValue ); fMap.put( fieldName, mapValue ); } } /** * @see openadk.library.tools.mapping.FieldAdaptor#getSIFValue(java.lang.String, openadk.library.SIFTypeConverter, openadk.library.tools.mapping.FieldMapping) */ public SIFSimpleType getSIFValue( String fieldName, SIFTypeConverter typeConverter, FieldMapping mapping ) { if( fMap.containsKey( fieldName ) ){ Object value = fMap.get( fieldName ); return fromMapValue( fieldName, value, typeConverter ); } else { // No value in the Map. Return null return null; } } /** * Gets the <code>Map</code> being used for SIF data mapping operations * @return The <code>Map</code> being used for SIF data mapping operations */ public Map getMap() { return fMap; } /** * Sets the <code>Map</code> being used for SIF data mapping operations * @param map The <code>Map</code> to be used for SIF data mapping operations */ public void setMap( Map map ) { fMap = map; } /** * Gets the keyset of the underlying Map * @return the keyset of the underlying Map */ public Set keySet() { return fMap.keySet(); } /** * This setting influences inbound mapping operations. If set to <code>True</code>, * data coming from SIF can overwrite existing values in the Map. The * default value is <code>False</code> * @param overwriteValues <code>True</code> to overwrite existing values in the * Map with data from SIF */ public void setOverwriteValues(boolean overwriteValues) { fOverwriteValues = overwriteValues; } /** * Returns whether this class will overwrite existing values in the Map * during inbound mapping operations of data coming from SIF. * @return True if this class should overwrite existing values in the Map */ public boolean getOverwriteValues() { return fOverwriteValues; } /** * From the Variables interface. Always returns true because * this class allows variables with any name to be tried * @param varName * @return true */ public boolean isDeclaredVariable(String varName) { // Always return true because this class doesn't care if the // variable has been declared or not. Allow it to be tried return true; } /** * Get the specified field from the Map for a JXPath variable * * @param varName The name of the field * @return The object or an empty string if the field does not exist */ public Object getVariable(String varName) { if( fMap.containsKey( varName ) ){ return fMap.get( varName ); } return ""; } /** * Declares a field for the JXPath variable and assigns the value * @param varName The name of the field * @param value The value to assign to the field */ public void declareVariable(String varName, Object value) { fMap.put( varName, value ); } /** * Removes the underlying variable from the Map for JXPath support * @param varName */ public void undeclareVariable(String varName) { fMap.remove( varName ); } }