All posts by n4nadm

getTimestamp()

   public String getTimestamp(Container container) throws StreamTransformationException {
      String DATE_FORMAT_NOW = "yyyyMMdd_HHmmss_SSS";
      Calendar cal = Calendar.getInstance();
      java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(DATE_FORMAT_NOW);
      return sdf.format(cal.getTime());
   }

GlobalContainer

Per condividere un valore fra le UDF di un mapping

   public String initCounter(Container container) throws StreamTransformationException {
      container.getGlobalContainer().setParameter("COUNTER", "0");
      return in;
   }

   public String increaseCounter(Container container) throws StreamTransformationException {
      int theCounter = (new Integer((String) container.getGlobalContainer().getParameter("COUNTER"))).intValue();
      theCounter++;
      container.getGlobalContainer().setParameter("COUNTER", String.valueOf(theCounter));
      return String.valueOf(theCounter);
   }

getSystemName

Utile come input ad un FixedValue laddove l’output dipende dal tipo di ambiente sviluppo, test o produzione.

   public String getSystemName(String dummy, Container container) throws StreamTransformationException{
      /* Ritorna il SysID dell'istanza PI in esecuzione */
      return System.getProperty("SAPSYSTEMNAME");
   }

SOAPLookup

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;

import javax.xml.transform.stream.StreamResult;

import com.sap.aii.mapping.api.AbstractTrace;
import com.sap.aii.mapping.lookup.*;
import com.sap.aii.mappingtool.tf7.rt.*;

import javax.xml.transform.dom.DOMSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import javax.xml.parsers.*;

import org.w3c.dom.*;

/*
* * Chiamata del communication channel chName relativo al business system
* receiver busSys. * Il parametro emailValue e’ relativo allo specfico
* webservice e rappresenta il parametro d’ingresso allo stesso.
*/ public String SOAPinvoke(String chName, String busSys, String emailValue, Container container) {
AbstractTrace trace = container.getTrace();
String internalID = “”;
try {
/*
* * Pass the Business System and Communication Channel as input to the *
* getChannel(). * BS_SOAPLOOKUP – Business System *
* CC_Webservice_SOAP_CURRENCY_CONVERTOR – Receiver SOAP Adapter
*/ Channel channel = LookupService.getChannel(busSys, chName);
SystemAccessor accessor = LookupService.getSystemAccessor(channel);
InputStream inputStream = null;
/*
* * Construct the SOAP Request Message using the InputParameters * emailValue
* is the Input Parameter.
*/ /* LA SEGUENTE ISTRUZIONE E’ RELATIVA ALLO SPECIFICO WEBSERVICE */ Document req = createRequestPayload(
emailValue);
/* ============================================================ */ String SOAPxml = returnXML(req);
inputStream = new ByteArrayInputStream(SOAPxml.getBytes());
XmlPayload payload = LookupService.getXmlPayload(inputStream);
/*
* * The SOAP call is made here and the response obtained is in the *
* SOAPOutPayload.
*/ Payload SOAPOutPayload = accessor.call(payload);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream inp = SOAPOutPayload.getContent();
Document doc = builder.parse(inp);
/* LA SEGUENTE ISTRUZIONE E’ RELATIVA ALLO SPECIFICO WEBSERVICE */ internalID = returnResponse(doc);
/* ============================================================ */ } catch (Exception e) {
trace.addWarning(“Error” + e);
}
return internalID;
}

/*
* * Crea il payload di request per il webservice da invocare. * Questa funzione
* dipende dallo specifico webservice.
*/ private static Document createRequestPayload(String emailValue) throws ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
doc.setXmlStandalone(true);
Element el = doc.createElementNS(“http://sap.com/xi/SAPGlobal20/Global”, “glob:CustomerByElementsQuery_sync”);
Node nroot = doc.appendChild(el);
Node ncsbe = nroot.appendChild(doc.createElement(“CustomerSelectionByElements”));
el = doc.createElementNS(“http://sap.com/xi/AP/CustomerExtension/BYD/A1WY2”,
“a1w:ExternalUnicCode_EA8AE8AUBVHCSXVYS0FJ1R3ON”);
Node neuc = ncsbe.appendChild(el);
Node nsbt = neuc.appendChild(doc.createElement(“SelectionByText”));
Node niec = nsbt.appendChild(doc.createElement(“InclusionExclusionCode”));
niec.setTextContent(“I”);
Node nibtc = nsbt.appendChild(doc.createElement(“IntervalBoundaryTypeCode”));
nibtc.setTextContent(“1”);
Node nlbn = nsbt.appendChild(doc.createElement(“LowerBoundaryName”));
nlbn.setTextContent(emailValue);
Node npc = nroot.appendChild(doc.createElement(“ProcessingConditions”));
Node nqhui = npc.appendChild(doc.createElement(“QueryHitsUnlimitedIndicator”));
nqhui.setTextContent(“false”);
return doc;
}

/* * Ritorna la String relativa al DOM dell’XML. */ private static String returnXML(Document doc)
throws javax.xml.transform.TransformerFactoryConfigurationError, javax.xml.transform.TransformerException {
javax.xml.transform.Transformer transformer = javax.xml.transform.TransformerFactory.newInstance()
.newTransformer();
StringWriter output = new StringWriter();
javax.xml.transform.Source input = new DOMSource(doc);
transformer.transform(input, new StreamResult(output));
return output.toString();
}

/*
* * Ritorna il payload relativo alla risposta del webservice invocato. * Questa
* funzione dipende dallo specifico webservice.
*/ static private String returnResponse(Document doc) throws XPathExpressionException {
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();
Node nroot = ((NodeList) xpath.compile(“//InternalID/text()”).evaluate(doc, XPathConstants.NODESET)).item(0);
return nroot.getNodeValue();
}


removeSUPPRESS

   public void removeSUPPRESS(String[] inp, ResultList result, Container container)
         throws StreamTransformationException {
      result.clear();
      for (int i = 0; i < inp.length; i++) {
         if (!(inp[i].equals(ResultList.SUPPRESS)) && !(inp[i].equals("")) && !(inp[i].equals(null))) {
            result.addValue(inp[i]);
         }
      }
      return;
   }

Rimuove gli elementi ResultList.SUPPRESS e <null> dal contesto.

Dato il seguente payload in inbound

<?xml version="1.0" encoding="UTF-8"?>
<ns0:MT_A xmlns:ns0="urn:develop:n4n.eu:SUPPRESS">
	<row>
		<KEY>FFX</KEY>
		<DATA>A</DATA>
	</row>
	<row>
		<KEY>AAA</KEY>
		<DATA>B</DATA>
	</row>
	<row>
		<KEY>AAA</KEY>
		<DATA>C</DATA>
	</row>
	<row>
		<KEY>FFX</KEY>
		<DATA>D</DATA>
	</row>
</ns0:MT_A>

occorre produrre in outbound un analogo payload con solo i row il cui  KEY = ‘FFX’.

Dato il mapping sotto, si visualizzano le code sulla removeContext.

Si può constatare che la removeContext rimuove i contesti SUPPRESS (grigi), Change Context, e conserva i valori SUPPRESS (azzurri) corrispondenti agli elementi senza FFX.

dove

Aggiungendo removeSUPPRESS dopo la removeContext si produrrà il seguente risultato

dove gli elementi SUPPRESS (azzurri) sono stati rimossi lasciando solo quelli relativi ai row con FFX.


safeSubstr

   public String safeSubstr(String value, int startPos, int length, Container container)
         throws StreamTransformationException {
      /*
       * @Author: Nicola Martella | www.nick4name.eu La funzione ritorna la
       * sottostringa di value a partire da startPos (in base 0) per la lunghezza
       * length. Es1: value: "ABCDEFGHIJ" startPos=6 length=3 ret: "GHI" Se la
       * posizione di length a partire da startPos eccede la lunghezza di value, viene
       * ritornata la sottostringa a partire da startPos per tutta la lunghezza
       * rimanente. Es2: value: "ABCDEFGHIJ" startPos=6 length=10 ret: "GHIJ" Se la
       * posizione di startPos e' maggiore della lunghezza di value, viene ritornata
       * una stringa vuota. Es3: value: "ABCDEFGHIJ" startPos=11 length=3 ret: "" Se
       * value è null, viene ritornata una stringa vuota. Es4: value: null startPos=0
       * length=3 ret: "" Se length e/o startPos sono < 0 vengono posti a 0.
       */
      if (value == null)
         return "";
      if (length < 0)
         length = 0;
      if (startPos < 0)
         startPos = 0;
      int toPos = startPos + length;
      if (toPos > value.length()) {
         toPos = value.length();
      }
      if (startPos > value.length()) {
         startPos = value.length();
      }
      return value.substring(startPos, toPos);
   }

Generazione di contesti correlati (SplitByValue intelligente)

Questo snippet si applica quando, a fronte di due differenti contesti correlati fra loro, si vogliono ottenere più contesti che rappresentino la correlazione.

Un esempio può essere il contesto TESTI con testi in lingua diversa ed il contesto LINGUE DEI TESTI. Si vogliono ottenere tanti contesti quante sono le lingue e in ciascun contesto i testi per quelle lingue.

Il requisito è che il contesto LINGUE DEI TESTI sia ordinato e che gli item del contesto dei TESTI siano in corrispondenza con gli item del contesto LINGUE DEI TESTI.

public void SplitByValueChange(String[] data, String[] criteria, ResultList result, Container container) throws StreamTransformationException{
/*
Dati due array in input, data e criteria, genera tanti contesti di data quante sono le rotture di livello di criteria.
Nessuno dei due array dev'essere vuoto o null e la dimensione di entrambi dev'essere la stessa.
*/
   result.clear();
   if( StringManager.isArrayNull(criteria) || StringManager.isArrayNull(data)) {
return;
}
   if( criteria.length != data.length ){
return;
}
   String t = criteria[0];
   for (int i = 0; i < criteria.length; i++){
      if(!criteria[i].equals(t)){
          result.addContextChange();
          t = criteria[i];
       }
       result.addValue(data[i]);
   }
}