You can perform attribute transformations interactively in the following ways:
Table 14 lists the standard transformations for which Map Designer can generate code.
You can create customized transformations in either of the following ways:
This section describes how to implement the following kinds of custom transformations:
Customer.CustomerStatus = 'Inactive' if SAP_CustomerMaster.DeleteInd = 'X'.
Otherwise, CustomerStatus = 'Active'.
You can create a Custom transformation and write the entire piece of code to implement the content-based logic yourself. However, a better approach is to start by creating a Move transformation between DeleteInd (in the SAP_CustomerMaster object) and CustomerStatus (see "Copying a source attribute to a destination attribute" for the procedure to move attributes).
As a result, Map Designer generates the move-transformation, as shown in the following sample code:
{ Object _cw_CpBTBSourceValue = null; // // RETRIEVE SOURCE // --------------- // // Retrieve the source value from the source business object and // place it in a local variable for code safety. // _cw_CpBTBSourceValue = ObjSAP_CustomerMaster.get("DeleteInd"); // // SET DESTINATION // --------------- // // Put the source value into the destination business object // attribute. // { Object _cw_SetSrcVal = _cw_CpBTBSourceValue; BusObj _cw_SetDestBusObj = ObjCustomer; String _cw_SetDestAttr = "CustomerStatus"; // // Set the destination value only if neither // source nor destination is null. // if ((_cw_SetSrcVal != null) && (_cw_SetDestBusObj != null)) { if (dataValidationLevel >= 1) { if (!_cw_SetDestBusObj.validData(_cw_SetDestAttr, _cw_SetSrcVal)) { String warningMessage = "Invalid data encountered when attempting to set the value of the \'_cw_SetDestAttr\' attribute of BusObj \'_cw_SetDestBusObj\' while running map \'" + getName() + "\'. The invalid value was \'" + _cw_SetSrcVal + "\'."; // // Log a warning about this failure. // logWarning(warningMessage); if (failOnInvalidData) { // // Fail the map execution with a warning message. // throw new MapFailureException(warningMessage); } } } // SECTION THAT NEEDS TO BE UPDATED WITH THE LOGIC if (_cw_SetSrcVal != null) { if (_cw_SetSrcVal instanceof BusObj) { // // Since BusObjs are not immutable, we need to make // a copy of the source object before actually // putting it into the destination attribute. // _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, ((BusObj)_cw_SetSrcVal).duplicate()); } else if (_cw_SetSrcVal instanceof BusObjArray) { // // Since BusObjs are not immutable, we need to make // a copy of the source object before actually // putting it into the destination attribute. // _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, ((BusObjArray)_cw_SetSrcVal).duplicate()); } else { // // Since our version of simple data types are immutable in // Java (Strings included), we do not have to make a copy // of the source value here. // _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, _cw_SetSrcVal); } } } } } // HERE IS THE MODIFIED CODE if (_cw_SetSrcVal != null) { if (((String)_cw_SetSrcVal).equals("X")) _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, "Inactive"); else _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, "Active"); } } } }
Select Save from Activity Editor File menu to save the changes.
Customer.CustomerStatus = 'Inactive' if Verb = 'Create'. Otherwise, CustomerStatus = 'Active'.
Follow the procedure in Content-based logic, but use the following conditional statement to replace the section of the generated code:
// HERE IS THE MODIFIED CODE if (_cw_SetSrcVal != null) { if (ObjSAP_CustomerMaster.getVerb() .equalsIgnoreCase("Create")) _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, "Inactive"); else _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr,"Active");
Map SAP_CustomerMaster.State into Customer.CustomerAddress.State. If SAP's state is missing, default to CA.
Notice that before the destination attribute is set to the source value, the code checks if the source attribute is not equal to null.
Example: In this example, if the source data is missing, set the destination attribute to a default value.
Start by moving SAP_CustomerMaster.State into Customer.CustomerAddress.State. Change the condition statement to the following:
// HERE IS THE MODIFIED CODE if (_cw_SetSrcVal != null) _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, _cw_SetSrcVal); else _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, "CA"); _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, "CA");
When you need to check for the value of the calling context, use the built-in variable strInitiator, which is of type String.
Example: To check if the calling context is EVENT_DELIVERY, use the following statement:
if (strInitiator.equals(MapExeContext.EVENT_DELIVERY)) //rest of the code
Map SAP_CustomerMaster.State into Customer.CustomerAddress.State. If SAP's state is missing, stop the map from executing.
Start by moving SAP_CustomerMaster.State into
Customer.CustomerAddress.State. Then add one
more if() statement to check if the State attribute for SAP is
equal to null. The generated code looks like the following:
{ Object _cw_CpBTBSourceValue = null; // // RETRIEVE SOURCE // --------------- // // Retrieve the source value from the source business object and // place it in a local variable for code safety. // _cw_CpBTBSourceValue = ObjSAP_CustomerMaster.get("State"); // // SET DESTINATION // --------------- // // Put the source value into the destination business object // attribute. // { Object _cw_SetSrcVal = _cw_CpBTBSourceValue; BusObj _cw_SetDestBusObj = ObjCustomer; String _cw_SetDestAttr = "CustomerAddress.State"; // New code if (_cw_SetSrcVal == null) { String errorMessage = "Data in the state attribute is missing"; logError(errorMessage); // // Fail the map execution with a warning message. // throw new MapFailureException(errorMessage); } // End of new code // // Set the destination value only if neither // source nor destination is null. // else if ((_cw_SetSrcVal != null) && (_cw_SetDestBusObj != null)) { if (dataValidationLevel >= 1) { if (!ObjCustomer.validData("CustomerAddress.State", _cw_SetSrcVal)) { String warningMessage = "Invalid data encountered when attempting to set the value of the \"CustomerAddress.State\" attribute of BusObj \'ObjCustomer\' while running map \'" + getName() + "\'. The invalid value was \'" + _cw_SetSrcVal + "\'."; // // Log a warning about this failure. // logWarning(warningMessage); if (failOnInvalidData) { // // Fail the map execution with a warning message. // throw new MapFailureException(warningMessage); } } } if (_cw_SetSrcVal != null) _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, _cw_SetSrcVal); } } }
If the map is run and the State attribute is not set, an error message is produced in both a dialog window and on the server screen. The message on the server screen is similar to the following:
[1999/09/22 17:58:51.008] [Server] Sub_SaCwCustomerMaster: Error Data in the state attribute is missing
The map stops executing.
try { // your code } catch (Exception e) { throw new MapFailureException(e.toString()); }
Notice how the example in Forcing a map to fail if the source data Is missing uses the logError() method to display the error message on the screen. You can use messages provided in the generic messages file, CWMapMessages.txt, which is stored in \DLMs\messages. See Appendix A, Message files, for more information about message files.
CWMapMessages.txt has the following format:
# critical data is missing error 10 Data in the {1} attribute is missing. Map execution stopped. # Another error 11 Another error message
Notice that instead of {1} you can use the word State to correspond directly to the error that needs to be displayed. If implemented, however, the message is no longer generic. If another attribute also has critical data, you need another message in the message file specific to that particular attribute.
To display message #10, use the following code:
logWarning(10, "State");
The word State replaces {1} in the message text.
The following message is displayed in the InterChange Server log file:
[1999/09/23 10:17:43.648] [Server] Sub_SaCwCustomerMaster: Warning 10: Data in the State attribute is missing. Map execution stopped.
The Mapping API provides methods for date formatting in the
DtpDate class. Table 61 summarizes the date-formatting methods.
Table 61. Date-Formatting Methods of the DtpDate Class
Date Formatting | DtpDate Method |
---|---|
Getting the month name from a date |
getMonth(),
getShortMonth()
|
Getting the month value from a date |
getIntMonth(),
getNumericMonth()
|
Getting the day of the month |
getDayOfMonth(),
getIntDay()
|
Getting the day of the week |
getDayOfWeek(),
getIntDayOfWeek()
|
Getting the year from a date |
getYear(),
getIntYear()
|
Getting the hour value |
getHours()
|
Getting the minutes value from a date |
getMinutes(),
getIntMinutes()
|
Getting the seconds value from a date |
getSeconds(),
getIntSeconds()
|
Getting the number of milliseconds in the date |
getMSSince1970()
|
Getting the earliest date from a list |
getMinDate(),
getMinDateBO()
|
Getting the most recent date from a list |
getMaxDate(),
getMaxDateBO()
|
Parsing the date according to a specified format |
DtpDate()
|
Getting the date in a specified or default format |
toString()
|
Reformatting a date to the IBM-generic
date format |
getCWDate()
|
Adding days to date |
addDays()
|
Adding weekdays to date |
addWeekdays()
|
Adding years to date |
addYears()
|
Calculating days between dates |
calcDays()
|
Calculating weekdays between dates |
calcWeekdays()
|
Comparing dates |
after(),
before()
|
Using full month names |
get12MonthNames(),
set12MonthNames(),
set12MonthNamesToDefault()
|
Using short month names |
get12ShortMonthNames(),
set12ShortMonthNames(),
set12ShortMonthNamesToDefault()
|
Using weekday names |
get7DayNames(),
set7DayNames(),
set7DayNamesToDefault()
|
IBM uses the following date format in its generic business objects:
YYYYMMDD HHMMSS
This format is called the generic date format.
To convert an application-specific date to this generic format, use the getCWDate() method of the DtpDate class.
Example: To map the SAP date attribute into a generic date, perform a Copy of the source attribute (the SAP date string) into the destination attribute (the generic date string):
Copy the source attribute (the SAP date string) into a new DtpDate object (the generic date string) by parsing the SAP date string (YYYYMMDD) with the DtpDate() constructor.
The last section of the code should look like this:
// HERE IS THE MODIFIED CODE if (_cw_SetSrcVal != null) { try { DtpDate myDate = new DtpDate((String)_cw_SetSrcVal, "YMD"); _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, myDate.getCWDate()); } catch (DtpDateException de) { logError(5501); logInfo(de.getMessage()); } }
Example: To map the Clarify date attribute into the generic date, perform a Copy of the source attribute (the Clarify date string) into the destination attribute (the generic date string):
Copy the source attribute (the Clarify date string) into a new DtpDate object (the generic date string) by parsing the Clarify date string (MM/DD/YYYY HH:MM:SS) with the DtpDate() constructor.
The following code converts the Clarify date into the Generic date:
if (_cw_SetSrcVal != null) { try { DtpDate myDate = new DtpDate((String)_cw_SetSrcVal, "M/D/Y h:m:s"); _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, myDate.getCWDate()); } catch (DtpDateException de) { logError(5501); logInfo(de.getMessage()); } }
To map the Generic date into the Clarify format, use the following code:
if (_cw_SetSrcVal != null) { try { DtpDate myDate = new DtpDate((String)_cw_SetSrcVal, "YMD hms"); _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, myDate.toString("M/D/Y h:m:s", true)); } catch (DtpDateException de) { logError(5501); logInfo(de.getMessage()); } }
To convert from the generic date format to the SAP date format, perform the following steps:
Perform a Copy of the source attribute (the generic date string) into a new DtpDate object (the SAP date string) by parsing the generic date string (YYYYMMDD HHMMSS) with the DtpDate() constructor.
The following code fragment shows this generic-to-SAP date conversion:
// HERE IS THE MODIFIED CODE if (_cw_SetSrcVal != null) { try { DtpDate myDate = new DtpDate((String)_cw_SetSrcVal, "YMD hms"); _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, myDate.toString("YMD")); } catch (DtpDateException de) { logError(5501); logInfo(de.getMessage()); } }
To create a DtpDate object that is initialized with the current system date, use the DtpDate() constructor without any parameters:
DtpDate()
Example: To map the current date into the generic format, use the following code:
//get the current date DtpDate myDate = new DtpDate(); // format the date to the destination object's format and map _cw_SetDestBusObj.set(_cw_SetDestAttr, myDate.getCWDate());
To map the current date into the application-specific format, use the following code:
//get the current date DtpDate myDate = new DtpDate(); // format the date to the destination object's format and map _cw_SetDestBusObj.set(_cw_SetDestAttr, myDate.toString( "application format");
When writing transformation code, you may need to build complex Java expressions to reference a particular attribute, manipulate a string, or call an API method. You can enter these expressions manually in Activity Editor, or use Expression Builder to construct the expression interactively. Expression Builder is a utility available from within Activity Editor.
Tip: Alternatively, you can use Activity Editor's Graphical view.
To display Expression Builder, place the cursor at the position in Activity Editor where you want to insert the expression and do one of the following:
Figure 89 identifies the main components of Expression Builder.
Figure 89. Expression Builder dialog
This section describes how to use Expression Builder to perform the following kinds of string transformations:
Move SAP_CustomerMaster.CustomerName into Customer.AccountOpenedBy and convert all letters to uppercase text.
To use the toUpperCase() string manipulation functions, perform the following steps:
if (_cw_SetSrcVal != null) { // // Since our version of simple data types are immutable in // Java (Strings included), we do not have to make a copy // of the source value here. // _cw_SetDestBusObj.setWithCreate( _cw_SetDestAttr, _cw_SetSrcVal); }
The _cw_SetSrcVal variable contains SAP.CustomerName and _cw_SetDestAttr contains AccountOpenedBy.
If you know the method to use, add it to the line of code above; otherwise, you can use Expression Builder to help you find the correct method. To do this:
Result: The method call is inserted into the code.
The following string transformation uses string manipulation methods (such as length() and substring()) to move SAP_CustomerMaster.AddressLine1 into Customer.CustomerAddress.AddressLine1 and AddressLine2:
To perform this string transformation, follow these steps:
if (_cw_SetSrcVal != null) // // Since our version of simple data types are immutable in // Java (Strings included), we do not have to make a copy // of the source value here. // { _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, _cw_SetSrcVal); }
The _cw_SetSrcVal variable contains SAP.AddressLine1, and _cw_SetDestAttr contains CustomerAddress.AddressLine1.
You can either modify the code yourself or use Expression Builder. In either case, use the methods length(), substring(int, int), substring(int), and indexOf(int) methods of the String class.
if (_cw_SetSrcVal != null) { // first check the length of _cw_SetSrcVal if (((String)_cw_SetSrcVal).length() < 10) { // if it is less then 10, map it to AddressLine1 _cw_SetDestBusObj.setWithCreate( _cw_SetDestAttr, _cw_SetSrcVal); } else { // if the length is not less than 10, search for comma int index = ((String)_cw_SetSrcVal).indexOf(","); // if comma is found, take a substring of _cw_SetSrcVal up to // the comma and map it to AddressLine1 if (index != -1) _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, ((String)_Cw_SetSrcVal).substring(0, index)); // if comma is not found, take first 9 characters of // _cw_SetSrcVal and map them to AddressLine1 else _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, ((String)_Cw_SetSrcVal).substring(0, 9)); } }
if (_cw_SetSrcVal != null) { // first check the length of _cw_SetSrcVal if (((String)_cw_SetSrcVal).length() >= 10) { // if the length is not less than 10, search for comma int index = ((String)_cw_SetSrcVal).indexOf(","); // if comma is found, take a substring of _cw_SetSrcVal after // the comma and map it to AddressLine2 if (index != -1) _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, ((String)_Cw_SetSrcVal).substring(index + 1)); // if comma is not found, take all characters of // _cw_SetSrcVal starting at the 10th and map them to // AddressLine1 else _cw_SetDestBusObj.setWithCreate(_cw_SetDestAttr, ((String)_Cw_SetSrcVal).substring(9)); } }
If you write code yourself, make sure that the source data is not null or blank. To check whether the source attribute is null, use one of the following:
To check whether the source attribute is an empty string, do the following: