Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
fatihpense
Active Contributor
EDIFACT messages require a 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 exactly the same behavior.


You can put this script just before the "XML to EDI converter" step, or after "EDIFACT Post-processing" step. It is flexible and it can be used when the message body has the XML root element starting with M_, or the root element is Interchange.


You can map $B2B_SEG_COUNTER to any field. You can use the constant function in Integration Advisor.



 

Script


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.
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
}

 

GitHub Repository for Contributions


You can see this example & others at the GitHub repository. You can star the project or even watch👀 for all future updates!

Contributions are welcome! I can help with the description or the code if you want.

 

Related Blog Posts


This blog post by vicky20691 shares the XSLT version of a similar solution. You should use it before the "Envelope Handling" step.

 
4 Comments
Labels in this area