Groovy Examples

Go to list of examples

EDI Segment Counter

EDI Segment Counter

EDIFACT messages require total segment count in the segment UNT. X12 messages require the same information in segment SE data element 96.

In SAP Process Integration/Orchestration(PI/PO) this requirement was handled by mapping the constant $B2B_SEG_COUNTER to the relevant field. SAP Cloud Integration doesn't have this feature yet, but we can create a Groovy script that replicates the same behavior.

Note that groovy.util.Node returns String in Groovy IDE and a QName object in Cloud Integration. This behavior is flexible in the Groovy spec. getLocalName function handles this difference.

Script

Try it on Groovy IDE

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;


def Message processData(Message message) {

    String magicKeyword = '$B2B_SEG_COUNTER'

    def body = message.getBody(java.io.Reader)
    def parser = new XmlParser()
    def ediXmlDoc = parser.parse(body)
    
    Integer segmentCount = 0



    //find message and count segments inside
    ediXmlDoc.breadthFirst().findAll { possibleMessageNode ->
        // GroovyIDE returns String, Cloud Integration returns QName here.
        // println possibleMessageNode.name().getClass()
        // The implementation is flexible in the Class spec. .name() function returns java.lang.Object. 
        // It is possible that since this input has no namespace, it returns string.
        

        // it is a message node
        if ( getLocalName(possibleMessageNode).startsWith("M_") ){
            possibleMessageNode.breadthFirst().findAll { possibleSegmentNode -> 
                // it is a segment node
                if ( getLocalName(possibleSegmentNode).startsWith("S_") ){
                    // println possibleSegmentNode.name()
                    segmentCount ++
                }
            }
        }
    }

    // find nodes to be filled
    ediXmlDoc.breadthFirst().findAll { node ->
        if (node.localText().size() > 0 && node.localText().first() == magicKeyword ){
           node.value = segmentCount
        }
    }





    // Write document to body
    def sw = new StringWriter()
    def xmlNodePrinter = new XmlNodePrinter(new PrintWriter(sw))
    xmlNodePrinter.with {
        preserveWhitespace = true
    }
    xmlNodePrinter.print(ediXmlDoc)

    String result = sw.toString()
    message.setBody(result)

    return message;
    }


def String getLocalName( groovy.util.Node node ){
    def name = node.name() // can be java.lang.String or groovy.xml.QName or another object!
    String localName = ""
    if (name instanceof groovy.xml.QName) {
        groovy.xml.QName qname = (groovy.xml.QName) name
        localName = qname.getLocalPart()
    }
    else {
        localName = name.toString()
    }
    return localName
}

Input Body

<?xml version="1.0" encoding="UTF-8"?>
<Interchange>
	<S_UNA>:+.? '</S_UNA>
	<S_UNB>
		<C_S001>
			<D_0001>UNOC</D_0001>
			<D_0002>3</D_0002>
		</C_S001>
		<C_S002>
			<D_0004>Sender1</D_0004>
			<D_0007>11</D_0007>
			<D_0008>ABC</D_0008>
		</C_S002>
		<C_S003>
			<D_0010>Receiver2</D_0010>
			<D_0007>12</D_0007>
			<D_0014>DEF</D_0014>
		</C_S003>
		<C_S004>
			<D_0017>220129</D_0017>
			<D_0019>0341</D_0019>
		</C_S004>

	</S_UNB>
	<M_ORDERS>
		<S_UNH>
			<D_0062>1</D_0062>
			<C_S009>
				<D_0065>ORDERS</D_0065>
				<D_0052>D</D_0052>
				<D_0054>96A</D_0054>
				<D_0051>UN</D_0051>
			</C_S009>
			<C_S010>
				<D_0070>2</D_0070>
			</C_S010>
		</S_UNH>

		<S_BGM>
		</S_BGM>

		<S_DTM>
		</S_DTM>

		<S_UNT>
			<D_0074>$B2B_SEG_COUNTER</D_0074>
			<D_0062>1</D_0062>
		</S_UNT>
	</M_ORDERS>
	<S_UNZ>
		<D_0036>1</D_0036>
		<D_0020>1</D_0020>
	</S_UNZ>
</Interchange>

Expected Result Body

<Interchange>
    <S_UNA>:+.? '</S_UNA>
    <S_UNB>
      <C_S001>
        <D_0001>UNOC</D_0001>
        <D_0002>3</D_0002>
      </C_S001>
      <C_S002>
        <D_0004>Sender1</D_0004>
        <D_0007>11</D_0007>
        <D_0008>ABC</D_0008>
      </C_S002>
      <C_S003>
        <D_0010>Receiver2</D_0010>
        <D_0007>12</D_0007>
        <D_0014>DEF</D_0014>
      </C_S003>
      <C_S004>
        <D_0017>220129</D_0017>
        <D_0019>0341</D_0019>
      </C_S004>
    </S_UNB>
    <M_ORDERS>
      <S_UNH>
        <D_0062>1</D_0062>
        <C_S009>
          <D_0065>ORDERS</D_0065>
          <D_0052>D</D_0052>
          <D_0054>96A</D_0054>
          <D_0051>UN</D_0051>
        </C_S009>
        <C_S010>
          <D_0070>2</D_0070>
        </C_S010>
      </S_UNH>
      <S_BGM/>
      <S_DTM/>
      <S_UNT>
        <D_0074>4</D_0074>
        <D_0062>1</D_0062>
      </S_UNT>
    </M_ORDERS>
    <S_UNZ>
      <D_0036>1</D_0036>
      <D_0020>1</D_0020>
    </S_UNZ>
  </Interchange>