How to modify a specific element in a list of tuple in a custom function or operator

How to modify a specific element in a list of tuple in a custom function or operator

book

Article ID: KB0075728

calendar_today

Updated On:

Products Versions
TIBCO Streaming -

Description

How to modify a specific element in a list of tuple in a custom function or operator?

Issue/Introduction

How to modify a specific element in a list of tuple in a custom function or operator

Resolution

Complex tuples have fields which are tuples, lists, lists of tuples, lists of lists, and more complex combinations to any depth.

You may modify any tuple field directly. However, if you need to modify a list (by adding, reordering, or removing an index), you must instead make a copy of that list, make your changes to the copied list, and then update the parent tuple's list field using Tuple.setList().

Consider this example:

1) Task: Modify portfolio.holdings.transform.dbls values by multiplying all double values by a scaling factor.

2) The custom function implementation:
package com.sb.support;
import java.util.ArrayList;
import java.util.List;
import com.streambase.sb.CompleteDataType;
import com.streambase.sb.Tuple;
import com.streambase.sb.TupleException;
import com.streambase.sb.client.CustomFunctionResolver;

public class ModifyUtils {
  @SuppressWarnings("unchecked")
  @CustomFunctionResolver("doModCustomFunctionResolver0")
  public static Tuple doMod(Tuple arg0, Double arg1) {
    //Modify portfolioSch.holdings.transform.dbls (multiply all double values by a scaling factor)
    try {
      // Don't modify an empty list field
      if (!arg0.isNull("holdings")) {
        List<Tuple> holdings = (List<Tuple>) arg0.getList("holdings");
  (c1)  for (int ind_holdings = 0; ind_holdings<holdings.size(); ind_holdings++) {
          // Don't modify null elements and Don't modify an empty list field
          if ((holdings.get(ind_holdings) != null) && (!holdings.get(ind_holdings).isNull("transform"))) {
          List<Tuple> transforms = (List<Tuple>) holdings.get(ind_holdings).getList("transform");
  (c2)    for (int ind_transforms = 0; ind_transforms<transforms.size(); ind_transforms++) {
              // Don't modify null elements and Don't modify an empty list field
              if ((transforms.get(ind_transforms) != null) && (!transforms.get(ind_transforms).isNull("dbls"))) {
                // Make modifiable copy of the list
                ArrayList<Double> dbls = new ArrayList<Double>();
  (b)           dbls.addAll( (List<Double>) transforms.get(ind_transforms).getList("dbls") );
                for (int ind_dbls = 0; ind_dbls<dbls.size(); ind_dbls++) {
                  // Don't modify null elements
                  if (dbls.get(ind_dbls) != null) {
                    dbls.set(ind_dbls, dbls.get(ind_dbls)*arg1);
                  }
                } // loop
                // Set the tuple field with updated value
  (a)           transforms.get(ind_transforms).setList("dbls", dbls);
              }
            } // loop through transforms elements
          }
        } // loop through holdings elements
      }
    } catch (TupleException e) {
      e.printStackTrace();
    } catch (NullPointerException e) {
      e.printStackTrace();
    }
    return arg0;
  }
  public static CompleteDataType doModCustomFunctionResolver0(
    CompleteDataType arg0, CompleteDataType arg1) {
    return arg0;
  }
}

Following the rule to only modify tuple fields in-place, the tuple at line (a) (in the code snippet shown above) gets it's list field updated with a new list. This is the only place the input tuple is modified in this example.

Similarly, since changes are made to the values in a list, a duplicate of that list is created at (b) and changes are only made to the copy which will replace the original at (a).

To visit all instances of each outer list of tuples, we iterate at lines (c1) and (c2).

The outer lists do not need to be modified because the objects they point to in memory are not changed. If direct list index values need to be changed, or indexes added or removed, then the list needs to be copied following the pattern at (b) for modifying dbls.  In addition, the parent tuple of the list would need to have setList() called, thereby replacing the old list with the modified copy.