Null or Empty values

I need to copy variable x to variable y only if the value of the variable is not null or not empty or not string containing spaces.
I want to put in value “NULL” in ‘y’ if the value of the variable ‘x’ is null or empty or string containing spaces.

What are the best ways of doing this?

please ignore this message

Not sure this is THE best solution, though, I would use a branch

BRANCH (evaluate label => true)
SEQUENCE (label => (x=="") || (x==$null) || (x==" "))
MAP Y - NULL
SEQUENCE (label => $default)
Do wathever default

You can use a regular expression. See http://wmusers.com/forum/showthread.php?t=4448

Thank you, but the following is not catching empty value.
(x=="") || (x==$null) || (x==" "))

  1. Link that “reamon” provided is great relating to regular expressions.

But I have to do the check for > 30 variables. I was looking for some kind of copy condition that will solve this issue, instead of writting 30 branch stms like:

  1. Initialize all the variables with default values like “NULL”.
  2. In the map, have a copy condition which copies value only if not null, not empty and not empty strings…
    So after the map if the orig value ‘x’ is empty, I should get NULL and if ‘x’ has some value, then I should see that value.

Write a new service that uses the regex /[^ ]/
Call that service as a transformer for your 30+ vars

You can also use a Copy Condition.

  1. In the MAP step, create a link between x and y.
  2. Click on the link (it should make the line thicker)
  3. At the top right corner of your screen, you should see a field called Copy Condition (under Evaluate copy condition which should be set to True). Set Copy Condition to %x% == /[^ ]/
  4. The line between x and y will now turn blue to indicate that it’s a conditional link.

Note: if by spaces, you also mean tabs, returns, and new line characters, you should use this expression instead: %x% == /[^ \t\r\n]/ (per Rob’s post.)

PRO: No extra service or BRANCHes needed
CON: If you need to change the expression in the future, you will have to change it for each link, whereas with the service approach, you would only have to change it in one place. This could also be a PRO though if you wanted to change the expression for some links but not others.

  • Percio

I didn’t know the copy condition supported regex. Cool!

trim x
invoke PSUtilites.string:isNullOrBlank service and map output to result
branch on result
–sequence true, map ‘NULL’ to y
–sequence $default, map x to y

Add the copy condition as Percio suggested but with a tweak. Changing it to

%x% == /[^\s]/

will take care of all whitespaces.

You can also include the else part of the mapping (ie mapping for the null case) by clicking on the blue assignment arrow and setting the value. Make sure you uncheck the overwrite checkbox.

The copy condition should be %x% != /[*\s]/
and else part can be mapped as Rupindar suggested.

I am using this regular expression. It use to work; but not sure what happend its not working now. Its always going to the default branch. Is using these regular expressions have downsides and behaves depending on the version, environment?

Can you post the regex and sample data that is not matching?

I personally think that manually creating 30+ copy conditions is time wasting and heavy on future code maintenance. Copy conditions cannot be seen at a glance in WM Developer so you won’t really know what the code does unless you click on each and every map and check the contents of every copy condition. So with the risk of starting a religious war, I believe that copy conditions should be generally avoided if possible.

With that being said, I created a quick (and really dirty) Java service that will remove or replace all null or whitespace values in a document or document arrray, optionally replacing them with a string instead of just dropping the values.

So I’m suggesting the following approach:

  1. Do your map from document x to document y
  2. Call a service to remove all empty or null values in y

The code does not support subdocuments though, so you’ll have to call the java service for each subdocument.

Input:

replaceEmptyValuesIn/document (optional document)
replaceEmptyValuesIn/inputDocArray (optional document array)
replaceEmptyValuesIn/replaceWith (optional replacement string, rather than removing empty fields)
replaceEmptyValuesIn/checkEmpty (true/false string, empty string check)
replaceEmptyValuesIn/checkEoln  (true/false string, line end check)

Either document or document array, but not both, are allowed at the same time.

Output:

replaceEmptyValuesOut/document  (corrected document)
replaceEmptyValuesOut/inputDocArray (corrected input doc array)

Java code (should really be rewritten, it was created in something like half an hour but seems to work):

IDataCursor baseCursor = pipeline.getCursor();
IData inputScopeDoc = IDataUtil.getIData(baseCursor, "replaceEmptyValuesIn");
IDataCursor pipelineCursor = inputScopeDoc.getCursor();
IData inputDoc = IDataUtil.getIData(pipelineCursor, "document"); 
IData[] inputDocArray = IDataUtil.getIDataArray(pipelineCursor, "inputDocArray"); 

String eolnCheck = IDataUtil.getString(pipelineCursor, "checkEoln"); 
String checkEmptyStr = IDataUtil.getString(pipelineCursor, "checkEmpty"); 
String replaceWith = IDataUtil.getString(pipelineCursor, "replaceWith"); 
boolean checkEoln = false;
boolean checkEmpty = false;

if( eolnCheck != null && eolnCheck.equals( "true" ) ) {
    checkEoln = true;
}
if( checkEmptyStr != null && checkEmptyStr.equals("true") ) {
    checkEmpty = true;
}

try {
 int arrayIndex = 0;
 do {
   if (inputDocArray != null && inputDocArray.length > arrayIndex ) {
     inputDoc = inputDocArray[arrayIndex];
   }
   IDataCursor curs = inputDoc.getCursor();
   if (curs != null) {
            boolean moreElements = curs.first();
     while( moreElements ) {
       Object value = curs.getValue();
       String currentKeyName = curs.getKey();
       IData[] currentArray = IDataUtil.getIDataArray(curs, currentKeyName);
   
           if (value == null || ( checkEmpty && value.equals("") ) || 
                                 ( checkEoln && (value.equals("\r\n") || value.equals("\n") )) ) {  
                    if (replaceWith == null) {
                         moreElements = curs.delete();
                    } else {
                         curs.setValue(replaceWith);
                    }
            } else {
                   moreElements = curs.next();
            }
          }
     } //while
     arrayIndex++;
  } while ( inputDocArray != null && arrayIndex < inputDocArray.length);
    IData outputDocument = IDataFactory.create();
    IDataCursor outputDocCursor = outputDocument.getCursor();
    if(inputDocArray == null) {
      if(inputDoc != null) {
        IDataUtil.put(outputDocCursor, "document", inputDoc);
      }
    } else {
      IDataUtil.put(outputDocCursor, "document", inputDocArray);
    }
    IDataUtil.put(baseCursor, "replaceEmptyValuesOut", outputDocument);
    outputDocCursor.destroy();
} finally {
    pipelineCursor.destroy(); 
    baseCursor.destroy();
}

Hi Sig,

Thanks, but can you post the image of java service with input & output signature too as its confusing to what to pass as inputs. Here is what I have done as in attachment but its throwing null pointer exception.

Regards,
Satish

Hi use this code snippet
branch on x
Seq1 with label /.+/
map x to y
Seq2 with label default
in map step drop y

I have tested this and it works.
Please let me know whether it solves your problem

Did you tried the above and it should do the trick…

Let us know how it goes:

HTH,
RMG