Implementi​ng a CNiGraph Sink Map

This is long, but there are only three relatively simple questions.  i.e. what are the IID and  CLSID values to use for a sink map.  I've included a list of everything I've done so far to eliminate as many questions as may be posed.
I'm attempting to create a sink map for a dynamically created CNiGraph object in Visual C++ 7.1.3088 with Measurement Studio 7.0.0.341.  The purpose of the sink map is to intercept the right-click event on a CNiGraph object and display a popup menu.  This is the first time I've attempted to create a sink map so I'm a little lost and have a few questions on obtaining the correct IID's and CLSID's.
I've followed the directions to create a CCmdTarget object in Microsoft KB 181845, How to create a sink interface in a MFC-based COM client, but am stuck.  Below are the steps I've taken and some of the questions I have.  All the references to selecting functions are made in reference to the Visual Studio IDE.  i.e. Project->Add Class means select the project menu and then select the add class option.  Please, correct me wherever I'm wrong.
1. Created a CCmdTarget inherited class with automation in the class wizard (Project->Add Class).  This object is called CGraphViewGraphExt.
2. Get the idl file for the CNiGraph object by going to Tools->OLE/COM Object Viewer.  Expand Type Libraries in the left tree, scroll down to National Instruments CW UI 6.0 (Ver 1.6), right-click on it, and select view.  I then save this file as cwui.idl to save myself the trouble of having to dig in the OLE/COM object viewer over and over.
3. Per the directions in KB 181845 step 2, I find the IID of the CNiGraph, which is CWGraph.  My first question is which uuid do I use to reprsent the IID value?
I see in the cwui.idl file that there is a coclass CWGraph which uses the interfaces of _DCWGraph and _DCWGraphEvents which I assume is what I want.  This has a uuid of B68DBFAB-16A0-11CE-80BF-0020AF31CEF9.  Do I use this value as the IID or do I use the uuid at the top of the cwuid.idl file represented by D940E4E4-6079-11CE-88CB-0020AF6845F6.  This uuid represents the entire National Instruments CW UI 7.0 cwui.ocx typelib.  NOTE: I do not know why in the OLE/COM viewer the UI is titled with a version number 6.0 (see step 1 above) and why it is written as 7.0 in the cwui.idl file.  These are the same two files.
At the moment I'm using the CWGraph UUID of B68DBFAB-16A0-11CE-80BF-0020AF31CEF9 to represent my IID value step 2 of KB 181845.
4. After the graph is created with the command:
void CDialogWIndow::CreateGraph() {
    m_niGraph.Create("", WS_VISIBLE, CRect(0, 0, 0, 0), this, m_iNumGraphs, NULL, FALSE, bstrLic);   // resizing takes place later
  //  I make the following function calls per the step 3 in KB 181845.
    m_pGraphViewExt = new CGraphViewGraphExt();      //   create the inherited CCmdTarget object
    LPUNKNOWN pUnkSink = m_pGraphViewExt->GetIDispatch(FALSE);   // get a pointer to sinks IUnknown  
    AfxConnectionAdvise(m_pUnkSrc, IID_IGraphViewGraphExt, pUnkSink, FALSE, &m_dwCookie);   // create connection between source and sink
CDialogWindow is a CDialog inherited class.  The variables not declared above are defined as private members of CDialogWindow and have the following declarations:
CGraphViewGraphExt m_pGraphViewExt;
LPUNKNOWN m_pUnkSrc;
DWORD m_dwCookie;
/*   CWGraph UUID as defined by cwui.idl - B68DBFAB-16A0-11CE-80BF-0020AF31CEF9   */
static const IID IID_IGraphViewGraphExt =
{ 0xB68DBFAB, 0x16A0, 0x11CE, { 0x80, 0xBF, 0x00, 0x20, 0xAF, 0x31, 0xCE, 0xF9 } };  
My next question refers to question 3 on KB 181845.  m_pUnkSrc is defined by calling CoCreateInstance.  CoCreateInstance requires a CLSID.  How do I obtain the CLSID for the CNiGraph I create?  I haven't called CoCreateInstance in my code yet because I don't know how to obtain this value.  However, would the call look like CoCreateInstance(/* whatever the CLSID of CWGraph is*/, NULL, CLSCTX_SERVER, IID_IGraphViewGraphExt, (LPVOID*)m_pUnkSrc);   ?  i.e. do those appear to be the correct parameters?
This is where I'm stuck at.  Thanks in advance.

Hello
You would use the clsid of the CWGraph, not of the cwui type lib.
B68DBFAB-16A0-11CE-80BF-0020AF31CEF9
I attached two examples here. Dynamic graph events shows you how you would hook up events to a dynamically created graph control. UsingMStudioContextmenu.zip shows how you could use the mouse up event to set up a context menu on the graph. You can combine the two to get what you need.
After hooking up the events dynamically, you will see first chance exceptions being generated in the output window. These are "member not found" exceptions and can be ignored. These happen if you only define handlers for some of the events associated with the graph, but not all. If you want to get rid of the exceptions, you will need to define handlers for all the graph events, even if you dont use them. These also occur if you do not define stock properties for the cwgraph control. But these exceptions will not have any detrimental effects. This is just MFC behavior.
I generated the dispatch map protypes by using VC to add event handlers from a graph in another project. You get something like the following with VC.
ON_EVENT(<some other dlg class>, IDC_CWGRAPH2, DISPID_CLICK, ClickCwgraph2, VTS_NONE)
I change it to
DISP_FUNCTION_ID(<sink class name>,"Click",DISPID_CLICK,ClickCwgraph1,VT_EMPTY,​VTS_NONE)
and added the appropriate handler function.
I hope this helps
Message Edited by bilalD on 05-11-2006 10:18 AM
Bilal Durrani
NI
Attachments:
DynamicGraphEvents.zip ‏45 KB
UsingMStudioContextMenu.zip ‏47 KB

Similar Messages

  • How to implement static tables in XI Mapping

    I need to use a static table for lookup purposes in an XI mapping. I am using Java Mapping.
    -- This is a small  5 columns - 264 rows table, which is unlikely to be changed.

    Hi,
    U can maintained table in Xi and use the RFC lookup from graphical mapping this will avoid use of graphical mapping.
    Refer the below weblog for more infor:
    •     RFC lookup using JCO (without communication channel)
          /people/sravya.talanki2/blog/2005/12/21/use-this-crazy-piece-for-any-rfc-mapping-lookups
    •     RFC lookup with communication channel.
                     /people/alessandro.guarneri/blog/2006/03/27/sap-xi-lookup-api-the-killer
    Thnx
    Chirag

  • Map implementation vs. map reference query

    Hello all and Happy New Year.
    I've written a Map implementation to store and retrieve values for a a class that needs to hold 80,00+ entries; performance is an issue, especially since it's a bucketed map with multiple values mapping to one key. everything worked as planned, but it was abysmally slow... after reading a bit on container performance for inspiration, I'm become a bit unclear as to whether I should really implement the class as a Map at all, or whether it makes more sense to just use one of Sun's implementations (like LinkedHashMap, for eg) and simply include it as a reference in the class. Nearly half of the reference material alluded to the latter case, which I didn't expect at all.
    the question that's bothering me is this: when is a Map implementation preferable to a static reference, when I can just create a variable of type Map<String, List<String>> and use the entry set to do all of the work, since I really don't need to modify the method implementations? Is there a performance benefit, or is it just a matter of principle?
    Thanks in advance for your input.
    Melissa
    ____________________________

    jverd wrote:Dude, your question makes less than zero sense.how sad. maybe thiis will help...
    public class DuhReference {
    Map<Duh1, Duh2> duhImAReference = new HashMap<Duh1, Duh2>();
    vs.
    public class DuhImplementation<K, V>  implements Map<K, V> {
    //duh... gee, I guess this is the implementation then...
    }Hope that helps. "Dude".

  • Implementing Google Maps function into a program/website

    Hi, I was wondering if it would be possible to implement the function of google maps where typing a letter will bring the top searches for that letter into a website or program.

    You might try looking into Google's APIs:
    http://code.google.com/intl/en/more/

  • Events from dynamically created CNiGraph object

    Hi,
    My application requires me to create a variable number of CNiGraph objects at runtime. I'm plotting data from a file and I don't know in advance how many variables there will be. So, I'm dynamically creating the graph objects in the OnInitDialog() method of my CView derived class. The thing I'm stuck on is how to get the various messages from the graph when it is created dynamically like this. I can't use Class Wizard for the message maps because the number is variable. I suppose I could create a bunch of static message maps (more than I think I would ever need), but is there a cleaner way to do this? I'm using Visual C++ 6.0.
    Thanks, Bob

    Ok, I figured it out. You need to change the event sink map to use the ON_EVENT_RANGE instead of ON_EVENT. The help for ON_EVENT_RANGE tells you all you need to know.

  • Foreign key Mapping based on Data - in SQL Developer Data modeler

    Team
    Do SQL Developer Data modeler supports Foreign Key mapping based on the Data in the Schema rather defined at the DDL ? For e.g if we implement a Objects Relation ship mapping in Data base, we don't define Foreign keys at table creation.
    Toad does this feature through "AUTOMATIC FOREIGN KEYS MAPPING IN TOAD DATA MODELER" more info at (http://toadworld.com/Blogs/tabid/67/EntryId/905/Automatic-Foreign-Keys-Mapping-in-Toad-Data-Modeler.aspx)
    any one know how to implement through some scripts also helps me
    Regards
    Raj

    If you have table PKs defined and the candidate columns match those PK columns, then you can use the Discover Foreign Keys utility. Right mouse over the relational model name (node) in the left browser. It is about half way down the menu. I did a blog post about it last week on kentgraziano.com.

  • PI 7.1 : Taking a input PDF file and mapping it to a hexBinary attribute

    Hello All,
    We have a requirement which involves taking in an input PDF file and mapping it to a message type with binary attribute and sending it to an R3 system.
    Can anyone please detail the steps or point us to the correct documents for setting up the scenario.
    The scenario is file to Proxy adapter. The part which we need assitance is pulling up the input pdf and mapping it to binary field.
    Thanks.
    Kiran

    Thanks Praveen,Mayank,Sarvesh and Andreas for your  valuable help with the issue.
    I was able to successfully pick up the binary PDF file from a file server , encode it using Base 64 and post it to R3.
    I used the following code snippet and added the mentioned jar files to create a new jar file which was used as java mapping in the operation mapping.
    import com.sap.aii.mapping.api.StreamTransformation;
    import com.sap.aii.mapping.api.*;
    import com.sap.aii.utilxi.base64.api.*;
    import java.io.*;
    import java.util.*;
    public class Base64EncodingXIStandard implements StreamTransformation{
         String fileNameFromFileAdapterASMA;
         private Map param;
         public void setParameter (Map map)
              param = map;
              if (param == null)
                   param = new HashMap();
         public static void main(String args[])
              Base64EncodingXIStandard con = new Base64EncodingXIStandard();
              try
                   InputStream is = new FileInputStream(args[0]);
                   OutputStream os = new FileOutputStream(args[1]);
                   con.execute(is, os);
              catch (Exception e)
                   e.printStackTrace();
    public void execute(InputStream inputstream, OutputStream outputstream)
                   DynamicConfiguration conf = (DynamicConfiguration) param.get("DynamicConfiguration");
                   DynamicConfigurationKey KEY_FILENAME = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File","FileName");
                   fileNameFromFileAdapterASMA = conf.get(KEY_FILENAME);
                   if (fileNameFromFileAdapterASMA == null)
                        fileNameFromFileAdapterASMA = "ToBase64.txt";
              try
                   while ((len = inputstream.read(buffer)) > 0)
                        baos.write(buffer, 0, len);
                   str = Base64.encode(baos.toByteArray());     //buffer);
                   outputstream.write("<?xml version=\"1.0\" encoding=\"utf-8\"?><ROOT>".getBytes());
                   outputstream.write(("<FILENAME>" + fileNameFromFileAdapterASMA + "</FILENAME>").getBytes());
                   outputstream.write( ("<BASE64DATA>" + str + "</BASE64DATA></ROOT>" ).getBytes());
              catch(Exception e)
                   e.printStackTrace();
         byte[] buffer = new byte[1024*5000];
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         int len;
         String str = null;
    I had to do the following configuration settings
    1)  Create a Sender Comm Channel with Adapter Specific message attributes and Filename checkbox checked.
    2) Use the Java Mapping in the Operation mapping.
    The scenario is working smoothly with out any issues.
    Thanks.
    Kiran

  • Java Mapping: payload as mail attachment and dynamic file name .

    Hi,
    I have written this piece of java code.
    The code includes XPATH for fetching dynamic filename and the copysource( in, out ) to copy the content of payload as mail attchment.
    The code seems to work fine, when either of the functionality is implemented.
    but when both are implemented together ie parsing for xpath then again parsing to copy payload, then it doesnt executes the latter path i.e the payload is not fetched in the attachment.
    public class MailPackage implements StreamTransformation {
      public void setParameter(Map map) {
      public void execute(InputStream in, OutputStream out)
              throws StreamTransformationException {
      String mailSubject = "test mail";
      String mailSender = "aaaaaaaa";
      String mailReceiver = "[email protected]";
      String attachmentName = null;
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = null;
      factory.setNamespaceAware(false);
    factory.setValidating(false);
         try {
              builder = factory.newDocumentBuilder();
         Document doc = null;
          doc = builder.parse(in);
              String XPATH ="/*/Invoice/InvoiceHeader/InvoiceNumber/text()";
              Node fieldValueNode = org.apache.xpath.XPathAPI.selectSingleNode(doc,XPATH);
              System.out.print(fieldValueNode);
              attachmentName = fieldValueNode.getNodeValue() +".xml";
      String boundary = "--";
      String mailContent = "This is a sample file";
      String CRLF = "\r\n";
        //     create XML structure of mail package
        String output ="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
               + "<ns:Mail xmlns:ns=\"http://sap.com/xi/XI/Mail/30\">"
               + "<Subject>" + mailSubject     + "</Subject>"
               + "<From>" + mailSender     + "</From>"
               + "<To>" + mailReceiver     + "</To>"
               + "<Content_Type>multipart/mixed; boundary=\"" + boundary + "\"</Content_Type>"
               + "<Content>";
        out.write(output.getBytes());
        // create the declaration of the MIME parts
        //First part
        output = "--" + boundary + CRLF
               + "Content-Type: text/plain; charset=UTF-8" + CRLF
               + "Content-Disposition: inline" + CRLF + CRLF
               + mailContent + CRLF
        //Second part
        + "--" + boundary + CRLF
        + "Content-Type: application/xml; name=" + attachmentName + CRLF
        + "Content-Disposition: attachment; filename=" + attachmentName + CRLF + CRLF;
        out.write(output.getBytes());
        //Source is taken as attachment
        copySource(in, out);
        out.write("</Content></ns:Mail>".getBytes());
      } catch (Exception ie) {
        throw new StreamTransformationException(ie.getMessage());
    protected static void copySource(InputStream in, OutputStream out)throws IOException {
        byte[] bbuf = new byte[in.available()];
        int bblen = in.read(bbuf);
       if (!(bblen < 0)) {
          String sbuf = new String(bbuf);
           //replace all control characters with escape sequences
         sbuf = sbuf.replaceAll("&", "&amp;");
         sbuf = sbuf.replaceAll("\"", "&quot;");
         sbuf = sbuf.replaceAll("'", "&apos;");
        sbuf = sbuf.replaceAll("<", "&lt;");
        sbuf = sbuf.replaceAll(">", "&gt;");
        out.write(sbuf.getBytes());
    Povide your suggestions.

    Hi,
    This is the sample o/p that I get by opening the mail attachment using notepad.
    <?xml version="1.0" encoding="UTF-8"?>
    <InvoiceTransmission><InvoiceTransmissionHeader><InvoiceCreationDate>2008-12-03T00:00:00</InvoiceCreationDate><Version>2.0.2</Version></InvoiceTransmissionHeader><Invoice><InvoiceHeader><CustomerEntityID>LH</CustomerEntityID><IssuingEntityID>009140559</IssuingEntityID><InvoiceNumber>913353669</InvoiceNumber><InvoiceIssueDate>2008-12-03</InvoiceIssueDate><InvoiceType InvoiceTransactionType="OR">INV</InvoiceType><InvoiceDeliveryLocation>aaa</InvoiceDeliveryLocation><TaxInvoiceNumber>Not Applicable</TaxInvoiceNumber><InvoiceCurrencyCode>USD</InvoiceCurrencyCode><InvoiceTotalAmount>517174.63</InvoiceTotalAmount><InvoiceIDDetails InvoiceIDType="BT"><InvoiceIDVATRegistrationNumber>0000000000</InvoiceIDVATRegistrationNumber><InvoiceIDName1>aaaaaaaaaaaaaaa</InvoiceIDName1><InvoiceIDName2>bbbbbbHKG</InvoiceIDName2><InvoiceIDCity>ccccccccc ccccc</InvoiceIDCity><InvoiceIDCountryCode>HK</InvoiceIDCountryCode></InvoiceIDDetails><InvoiceIDDetails InvoiceIDType="II"><InvoiceIDVATRegistrationNumber>0000000000</InvoiceIDVATRegistrationNumber><InvoiceIDName1>eeeeeeee</InvoiceIDName1><InvoiceIDName2>PAY BY WIRE TRANSFER</InvoiceIDName2><InvoiceIDCity>fffffffffffffff, NA</InvoiceIDCity><InvoiceIDCustomField ID="1"><InvoiceIDCustomFieldDescription>Company Registration Number</InvoiceIDCustomFieldDescription><InvoiceIDCustomFieldValue>0000000000</InvoiceIDCustomFieldValue></InvoiceIDCustomField></InvoiceIDDetails></InvoiceHeader><SubInvoiceHeader><InvoiceLine><ItemNumber>001</ItemNumber><ItemQuantity><ItemQuantityType>IN</ItemQuantityType><ItemQuantityFlag>GR</ItemQuantityFlag><ItemQuantityQty>28134.000</ItemQuantityQty><ItemQuantityUOM>USG</ItemQuantityUOM></ItemQuantity><ItemQuantity><ItemQuantityType>DL</ItemQuantityType><ItemQuantityFlag>GR</ItemQuantityFlag><ItemQuantityQty>106498.775</ItemQuantityQty><ItemQuantityUOM>LT</ItemQuantityUOM></ItemQuantity><ItemDeliveryReferenceValue ItemDeliveryReferenceType="DTN">590365</ItemDeliveryReferenceValue><ItemDeliveryReferenceValue ItemDeliveryReferenceType="!
    ARN">DAL
    CH</ItemDeliveryReferenceValue><ItemDeliveryReferenceValue ItemDeliveryReferenceType="FNO">mmmmmmmmm</ItemDeliveryReferenceValue><ItemDeliveryLocation>pppp</ItemDeliveryLocation><ItemReferenceLocalDate
    If you notice the problem is, the undesired "exclamation mark" that gets added in some fields before the actual value.
    In the above case.. look at "ItemDeliveryReferenceType="! ARN">DAL"
    the exclamation mark before value "ARN is unwanted, which leads to improper XML formation.
    Cant figure out why is this coming.
    Regards,
    Faria Mithani

  • Different mapping tools in the market --  For BPM mapping in XI

    Hi All
         I am more intersted in learning the BPM mapping tools(3rd party or any)
         Can any list out the different tools and which are the best ?
         Our company looking forward to implement XI (BPM's) with mapping tools
        Can any help me on this
    Regards
    Rakesh

    Hi Rakesh,
    plz have a look to <a href="http://help.sap.com/saphelp_nw04/helpdata/en/14/80243b4a66ae0ce10000000a11402f/frameset.htm">SAP Library: SAP Exchange Infrastructure</a> for understanding XI, BPM and Mappings.
    BPM has no special mapping tool. You can use Java, ABAP, XSLT and graphical Mapping (Message Mapping) at XI, for any case - BPM or not. 3rd Party has nothing to do with BPM or Mapping. That means a non SAP system.
    Regards,
    Udo

  • Java mapping runtime issue

    Hi,
    I have currently created a java mapping which unzips files and transforms plain text/falt files to xml according to a specific structure... So far so good. This stuff works perfectly when testing interface mapping in the repository. However at runtime it does not work, and this is where you clever guys come into the picture:-)
    It should be mentioned that the zip-file is dropped on a MQ-queue and picked up in XI and passed on to a BPM - the only thing the BPM does is to perform the java mapping and afterwards send one of the messages to R/3 and the other to CRM.
    The concrete error given at runtime in the PE is:
    Error handling for work item 000000718016
    Work item 000000718016: Object CL_SWF_XI_MSG_BROKER method CALL_TRANSFORMATION cannot be executed
    Parsing error before mapping: unexpected end-of-file (line 1, column 1)
    Hope somone can help me on this matter,
    Best regards,
    Daniel
    PS: In case it is of interest/use the java code used is this:
    package dk.post.xi.unzipAndConvert;
    import java.io.*;
    import java.util.Map;
    import java.util.HashMap;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    import com.sap.aii.mapping.api.MappingTrace;
    import com.sap.aii.mapping.api.StreamTransformation;
    import com.sap.aii.mapping.api.StreamTransformationConstants;
    import com.sap.aii.mapping.api.StreamTransformationException;
    public class UnzipMain implements StreamTransformation {
         private MappingTrace mappingTrace = null;
         private Map param = null;
         private StringBuffer currentXmlRecord = new StringBuffer();
        private StringBuffer currentPlainRecord = new StringBuffer();
        private int[][] dataRanges = null;
        private char[] charsInCurrentRange = new char[650];
         private String[] xmlTagNames = null;
         /* (non-Javadoc)
    @see com.sap.aii.mapping.api.StreamTransformation#setParameter(java.util.Map)
    Method must be implemented when class is implementing streamTransformation
           public void setParameter(Map param) {
            this.param = param;
            if (param == null) {
               this.param = new HashMap();
    (non-Javadoc)
    @see com.sap.aii.mapping.api.StreamTransformation#execute(java.io.InputStream, java.io.OutputStream)
    Main function -- called by XI to start execution of java mapping
           public final void execute(InputStream in, OutputStream out)
                throws StreamTransformationException
                //if no input, then cancel program execution
                if (in == null) {
                     throw new RuntimeException("Something wrong with input zip file - is null");
                //input <> null. Begin upzip operation
                try {
                     //test is only relevant outside of XI
                     if (param != null) {
                          mappingTrace = (MappingTrace) param.get(StreamTransformationConstants.MAPPING_TRACE );
                  ZipInputStream zip = null;
                     try {
                          zip = new ZipInputStream(in);
                          ZipEntry ze = null;
                          out.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><ns0:Messages xmlns:ns0=\"http://sap.com/xi/XI/SplitAndMerge\">".getBytes());
                          while ((ze = zip.getNextEntry()) != null) {
                               writeDebugInfo("File: " + ze.getName() + " with compressed size: " + ze.getCompressedSize());
                               scrutinize(zip,(ZipEntry) ze, out);
                          out.write("</ns0:Messages>".getBytes());
                     finally {
                          if (zip != null)
                               zip.close();
                          out.flush();
                          out.close();
                } catch (Exception e) {
                     throw new RuntimeException(e + "\nSomething went wrong...");
           //Unzip flat files and convert to xml
           private void scrutinize(ZipInputStream inStream,ZipEntry zipEntry, OutputStream outstream) throws Exception {
                long start = System.currentTimeMillis();
              InputStreamReader inStreamReader = null;
              BufferedReader buffReader = null;
              byte[] xmlBytes = null;
              try {
                   inStreamReader = new InputStreamReader(inStream);
                   buffReader = new BufferedReader(inStreamReader);
                 boolean masterData = zipEntry.getName().equals("PD-01-STAMDATA.DAT");
                 boolean creditData = zipEntry.getName().equals("PD-02-KREDITVURDERING.DAT");
                 String currentLine = null;
                 if (masterData) {
                      writeDebugInfo("- Begin reading and converting every line of MasterData...");     //out-comment this outside of XI, or compilation will fail (functionality is only available in XI)
                      outstream.write("<ns0:Message1><ns1:masterData_MT xmlns:ns1=\"http://pdk/xi/kob/importDataToSap\">".getBytes());
                        while ((currentLine = buffReader.readLine()) != null) {
                           //convert one line of credit data plain into an xml record structure
                           makeXmlRecord(currentLine,true);
                           //Write record XML to XI's outputstream (appends)
                           xmlBytes = currentXmlRecord.toString().getBytes();
                           outstream.write(xmlBytes);
                      outstream.write("</ns1:masterData_MT></ns0:Message1>".getBytes());
                      writeDebugInfo("- Finished reading and converting every line of MasterData...");     //out-comment this outside of XI, or compilation will fail (functionality is only available in XI)
                 if (creditData) {
                      writeDebugInfo("- Begin reading and converting every line of CreditData...");
                      outstream.write("<ns0:Message2><ns1:creditData_MT xmlns:ns1=\"http://pdk/xi/kob/importDataToSap\">".getBytes());
                      while ((currentLine = buffReader.readLine()) != null) {
                           //convert one line of credit data plain into an xml record structure
                           makeXmlRecord(currentLine,false);
                           //Write record XML to XI's outputstream (appends)
                           xmlBytes = currentXmlRecord.toString().getBytes();
                           outstream.write(xmlBytes);
                      outstream.write("</ns1:creditData_MT></ns0:Message2>".getBytes());
                      writeDebugInfo("- Finished reading and converting every line of CreditData...");
              } finally {
                   long timeUsed = System.currentTimeMillis() - start;
                   writeDebugInfo(zipEntry.getName() + "  - Write took: " + timeUsed + " ms");
                   writeDebugInfo("Final statement entered...\n");
           //check for invalid xml chars (plus a few other strange chars) in a plain text record and if any are found update the ranges of so they correspond to the new length of a record
           private int[][] checkRange(String currentPlainLine, boolean isMasterData) {
                int counter = 0;
                int beginRange = 0;
                int endRange = 0;
                //populate array with proper data ranges/intervals according to how data is to be split
                dataRanges = isMasterData ? new int[][] {{0,2},{2,12},{12,44},{44,47},{47,50},{50,295},{295,298},{298,356},{356,426},{426,496},{496,499},{499,506},{506,510},{510,518},{518,540},{540,546},{546,552},{552,558},{558,564},{564,570},{570,576},{576,582},{582,588},{588,594},{594,604}} : new int[][] {{0,2},{2,12},{12,20},{20,23},{23,26},{26,29},{29,44}};
                //ensure stringbuffer is empty
                currentPlainRecord.delete(0,currentPlainRecord.length());
                //insert the current plain text line into stringbuffer
                currentPlainRecord.append(currentPlainLine);
              //loop through outer array (array of ranges)
              for (int i = 0; i <= (dataRanges.length-1); i++) {
                   beginRange = dataRanges<i>[0];
                   counter = beginRange;
                   endRange = dataRanges<i>[1];
                   //loop through stringbuffer, based on the value-pairs of ranges/intervals in array of arrays
                   while (counter < endRange) {
                        switch (currentPlainRecord.charAt(counter)) {
                             case '&':
                                  currentPlainRecord.insert(counter+1,"amp;");          //insert 'amp;' after '&', so that syntax conforms to xml syntax requirements (&amp;)
                                  counter += 5;                                                   //increment counter so that it continues after insertet characters
                                  updateRange(counter,4);                                        //update the array of ranges so that is corresponds to the new range
                                  break;
                             case '\'':
                                  currentPlainRecord.replace(counter,counter+1,"&");     //replace '\'' with '&'
                                  currentPlainRecord.insert(counter+1,"apos;");          //insert 'apos;' after '\'', so that syntax conforms to xml syntax requirements (&apos;)
                                  counter += 6;                                                   //increment counter so that it continues after insertet characters
                                  updateRange(counter,5);                                        //update the array of ranges so that is corresponds to the new range
                                  break;
                             case '"':
                                  currentPlainRecord.replace(counter,counter+1,"&");     //replace '"' with '&'
                                  currentPlainRecord.insert(counter+1,"quot;");          //insert 'quot;' after '"', so that syntax conforms to xml syntax requirements (&quot;)
                                  counter += 6;                                                   //increment counter so that it continues after insertet characters
                                  updateRange(counter,5);                                        //update the array of ranges so that is corresponds to the new range
                                  break;
                             case '<':
                                  currentPlainRecord.replace(counter,counter+1,"&");     //replace '<' with '&'
                                  currentPlainRecord.insert(counter+1,"lt;");               //insert 'lt;' after '&', so that syntax conforms to xml syntax requirements (&lt;)
                                  counter += 4;                                                   //increment counter so that it continues after insertet characters
                                  updateRange(counter,3);                                        //update the array of ranges so that is corresponds to the new range
                                  break;
                             case '>':
                                  currentPlainRecord.replace(counter,counter+1,"&");     //replace '>' with '&'
                                  currentPlainRecord.insert(counter+1,"gt;");               //insert 'gt;' after '&', so that syntax conforms to xml syntax requirements (&gt;)
                                  counter += 4;                                                   //increment counter so that it continues after insertet characters
                                  updateRange(counter,3);                                        //update the array of ranges so that is corresponds to the new range
                                  break;
                             case 0x7F:
                                  currentPlainRecord.replace(counter,counter+1," ");     //replace 0x7F with ' '
                                  writeDebugInfo("-- Corrected the character 0x7F ('') to ' '");
                                  counter++;
                                  break;
                             case '‘':
                                  currentPlainRecord.replace(counter,counter+1," ");     //replace 0x91 ('‘') with ' '
                                  writeDebugInfo("-- Corrected the character '‘' to ' '");
                                  counter++;
                                  break;
                             case '›':
                                  currentPlainRecord.replace(counter,counter+1," ");     //replace 0x9B ('›') with ' '
                                  writeDebugInfo("-- Corrected the character 0x9B to ' '");                              counter++;
                                  break;
                             case '†':
                                  currentPlainRecord.replace(counter,counter+1," ");     //replace '†' with ' '
                                  writeDebugInfo("-- Corrected the character '†' to ' '");
                                  counter++;
                                  break;
                             default :
                                  counter++;
                                  break;
                return dataRanges;
           //update array of ranges so that is corresponds to the new range
           private void updateRange(int currentRange, int updateRangeBy) {
              for (int k = currentRange; k < dataRanges.length; k++) {
                   if (k != currentRange) {     //never update begin interval for the current range - only for the remaining intervals
                             dataRanges[k][0] += updateRangeBy;
                   dataRanges[k][1] += updateRangeBy;     //always update end intervals
           //convert one flat record line to a xml record structure
         private void makeXmlRecord(String currentPlainLine,boolean isMasterData) {
              dataRanges = checkRange(currentPlainLine,isMasterData);
              //clear StringBuffer
              currentXmlRecord.delete(0,currentXmlRecord.length());
              //get the correct set of xml tags to be used when performing mapping between plain text and xml
              if (isMasterData) {
                   xmlTagNames = new String[] {"dum1","kob_no","dum2","corp_status","legal_form","dum3","pr_protec_code","dum4","uri","email","emp_no_grp_code","exact_no_emp","dum5","founding_date","dum6","main_industry_code","industry_code1","industry_code2","industry_code3","industry_code4","industry_code5","industry_code6","industry_code7","industry_code8","dum7"};
              } else {
                   xmlTagNames = new String[] {"dum1","kob_no","rating_date","rating_value","risc_grp_code","currency","max_credit"};
              //copy all chars in stringBuffer to the specified char[]
              currentPlainRecord.getChars(0,currentPlainRecord.length(),charsInCurrentRange,0);
              //populate XML record structure
              currentXmlRecord.append("<record>");
              for (int i = 0; i < xmlTagNames.length; i++) {
                   currentXmlRecord.append("<" + xmlTagNames<i> + ">");
                   currentXmlRecord.append(charsInCurrentRange,dataRanges<i>[0],(dataRanges<i>[1])-(dataRanges<i>[0]));
                   currentXmlRecord.append("</" + xmlTagNames<i> + ">");
              currentXmlRecord.append("</record>");
         //write debug information to correct "place"
         private void writeDebugInfo(String debugInfo) {
              if (mappingTrace == null) {
                   System.out.println("Debug: " + debugInfo);
              } else {
                   mappingTrace.addInfo("Debug: " + debugInfo);

    Hi Alex,
    Thanks for your reply. First of all I was wondering if I missed something somewhere in my generel understanding of XI and BPM's!? - I kind of sense some irony/sarkasm in beginning of your reply:-) As far as I know BPM should have no trouble receing non-xml (in my case zip-files)!?
    Anyways here goes:
    1. Yes, this is also my impression that is should be possible somehow (we do currently run sp14). However, I havent yet figured out how to do it in this case. When trying to create interface mapping between the three involved software components, I get a 'MESS_MULTI_MAP_IF_WRONG_SWCV' three times. I've searched around without being able to find any information on the error. I does seem, though, like the problem is that all objects aren't in the same software component!! But this approach is of course the prefered one...
    2. Well - you got me there. Kind of expected someone to point that out:-) This is of course something to be looked into also in order to "improve"/"enhance" the program - though it, as already pointed out, works perfectly as is.
    3. This part I have also thought about - though quickly moved away from the idea, but that is only due to lacking insight/knowhow on the subject. Interesting weblog you have written, something so I will investigate further when  time allows for it:-)
    Best regards,
    Daniel

  • How to call a mapping in a PL/SQL proc ?

    Hi all,
    I want to create a PL/SQL proc to call my mappings in the right order, and to make other operations the mapping don't do.
    The mapping I want to call is located in the packages.
    How can I call it ?
    Thanks,
    Nico

    Hi Carsten,
    Thank you for trying to help me.
    I do have the "Main" method you are talking about, but this method need a parameter (called "p_status") that I don't know how to implement...
    The mapping I create and I want to call needs no parameter, that's why I don't understand...
    This is the beginning of the main proc of my mapping package :
    PROCEDURE Main(p_status OUT VARCHAR2,
    p_max_no_of_errors IN VARCHAR2 DEFAULT NULL,
    p_commit_frequency IN VARCHAR2 DEFAULT NULL,
    p_operating_mode IN VARCHAR2 DEFAULT NULL,
    p_bulk_size IN VARCHAR2 DEFAULT NULL,
    p_audit_level IN VARCHAR2 DEFAULT NULL,
    p_purge_group IN VARCHAR2 DEFAULT NULL) IS
    x_schema VARCHAR2(30);
    x_audit_id NUMBER;
    x_object_id NUMBER;
    x_env wb_rt_mapaudit.wb_rt_name_values;
    x_param wb_rt_mapaudit.wb_rt_name_value;
    x_result NUMBER;
    x_return_code NUMBER;
    BEGIN
    etc, etc....
    ----------------------------------------------------------------------------------------------------------------------

  • Mapping to a Lookup Table

    O.K. I have a basic Java question and how to do this the following using
    Java/JDO:
    I have a database table for a lookup class. It will have the following
    structure:
    Create Table ProductStatus
    Id bigint not null
    name char (20);
    In C++ I would have an Enumeration Type which constrains the value of the
    variable to the set of values in the database.
    In Java I was thinking that I would have a ProductStatus class and then in
    the Product Class I would have an instance as follows:
    public class Product {
    ProductStatus status;
    But I have now believe that this is wrong...
    From offline work I have been told that the correct JDO for what I want
    to do is as follows:
    <class name="Product">
    <extension vendor-name="kodo" key="table" value="JDO_PRODUCT"/>
    <extension vendor-name="kodo" key="pk-column" value="ID"/>
    <extension vendor-name="kodo" key="class-column" value="JDOCLASS"/>
    <extension vendor-name="kodo" key="lock-column" value="none"/>
    <field name="currency">
    <extension vendor-name="kodo" key="data-column" value="CURRENCY"/>
    </field>
    <field name="productStatus">
    <extension vendor-name="kodo" key="data-column" value="STATUS_ID"/>
    </field>
    </class>
    <class name="ProductStatus">
    <extension vendor-name="kodo" key="table" value="JDO_STATUS"/>
    <extension vendor-name="kodo" key="pk-column" value="ID"/>
    <field name="name">
    <extension vendor-name="kodo" key="data-column" value="NAME"/>
    </field>
    </class>
    My two questions are:
    1) What do I put for the Java code, both in the product class and for
    ProductStatus.... This is more a Java question than JDO... I have been
    told I am thinking in too much of a C++ way.... I keep wanting to have
    a ProductStatus as a Type Class and then have an instance variable in
    the Product class such as status that is of type: ProductStatus.
    But I have been told this is not the correct Java way to do things.
    How should this be done?
    2) I would have expected that the JDO for the ProductStatus field in the
    Product Class would have been a FK extension, but I had Abe White help me
    with this and he said generated the JDO file I have included.... so how is
    the Product.ProductStatus linking to the ProductStatus class ???? With the
    current JDO I don't see any link, either by name or by shared ID value....
    Obviously I am a total newbie to this and these are basic questions.
    Thanks to anyone who has the time to reply.
    Brian Smith

    Hi Brian --
    Java code:
    public class Product
         private ProductStatus status;
    public class ProductStatus
         private String name;
    Metadata:
    Exactly like you posted it.
    I'm not sure where you're getting confused on how the relation works. It's
    straightforward. The STATUS_ID column in the JDO_PRODUCT table holds the
    primary key value of the related ProductStatus instance. That's all there is
    to it. So, for example, the following Java code:
    ProductStatus stat = new ProductStatus ();
    stat.setName ("foo");
    Product prod = new Product ();
    prod.setProductStatus (stat);
    pm.currentTransaction ().begin ();
    pm.makePersistent (prod);
    pm.currentTransaction ().commit ();
    Would product SQL like:
    INSERT INTO JDO_PRODUCT (ID, STATUS_ID) VALUES (100, 101);
    INSERT INTO JDO_STATUS (ID, NAME) VALUES (101, 'foo');
    Note that the '101' value for STATUS_ID in the inserted JDO_PRODUCT row
    matches the '101' value for the ID (primary key) in the inserted JDO_STATUS
    row.
    If you wanted to simulate a C++ enumeration and at the same time get rid of
    the necessity of a second JDO_STATUS table that seems a little redundant
    (why have a table to hold a single piece of data?), you could do it in 2 ways.
    The simple way would be to just use static constants in the Product class for
    different possible statuses:
    public class Product
         public static final String STATUS_XXX = "xxx";
         public static final String STATUS_YYY = "yyy";
         private String status;
    And then just have the JDO_PRODUCT table have a VARCHAR column to hold the
    status string rather than having a STATUS_ID column that forms a relation to
    a separate table.
    The second way, which more closely mirrors C++ enumerations, is a little more
    complex. You keep the ProductStatus class, but make it non-persistent (note:
    the static-instance, private-constructor pattern below is the standard Java
    way of doing enums):
    public class ProductStatus
         // enumerate all possible product status values
         public static final ProductStatus XXX = new ProductStatus ("xxx");
         public static final ProductStatus YYY = new ProductStatus ("yyy");
         private String name;
         * Convenience method to return a status for a given name.
         public static ProductStatus forName (String name)
              if (XXX.getName ().equals (name))
                   return XXX;
              if (YYY.getName ().equals (name))
                   return YYY;
              throw new IllegalArgumentException (name);
         * Make constructor private to prevent creation of any status instances
         * with illegal values.
         private ProductStatus (String name)
              this.name = name;
         public String getName ()
              return name;
    Then in your Product class, keep a non-persistent ProductStatus instance and
    a persistent field with the status name. Use the javax.jdo.InstanceCallbacks
    interface to transfer the stored status name to/from the ProductStatus:
    public class Product
         implements InstanceCallbacks
         // used internally only; map this to the column in the JDO_PRODUCT table
         // holding the status name for the product; at runtime we'll use JDO
         // lifecycle callbacks to transfer the value to/from a ProductStatus
         // instance
         private String statusName;
         // mark this as non-persistent in the metadata
         private ProductStatus status;
         public void jdoPostLoad ()
              status = ProductStatus.forName (statusName);
         public void jdoPreStore ()
              statusName = (status == null) ? null : status.getName ();
         // rest of InstanceCallbacks methods can be implemented as no-ops...
    With Kodo, you could even implement your own FieldMapping to map status strings
    to ProductStatus instances, but that's getting really complicated for very
    little real advantage.
    Hope that helps.

  • Two Message Mappings in one Interface Mapping without using BPM

    Hello Experts,
    I have this scenario, please help me
    I have to execute two mappings of which one is a java mapping and then the other is a message mapping sequentially.
    The mapping is something like below
    Message1  -> (java Mapping) -> Message2
    Message2
    Message1 -> (Message Mapping) -> Message3
    Based on the value in Message2 I have to map Message1 to Message3
    I am not an expert in java so please give me options that doesn't involve changing of java code.
    The above 2 mappings have to be implemented in only one interface mapping.
    Suggestions please.

    Hi Ravi!
    You say message2 dependes on message1 and message3 is mapped from message1 but using also values from message2? But this means, that whole mapping dependes only on message1!
    So change your mapping and use the one not based on message2, but message1. Put these as a condition in interface determination and based on these values use the correct mapping.
    Peter
    p.s. I'm not sure, if I got your requirement correctly, but your target message dependes only on message1 (since message2 dependes on it too), so this whole mapping can be done as 1. Unfortunately, you'll probably have to change your java part. Bur definetely, Raj is right.
    Edited by: Peter Jarunek on Feb 20, 2008 5:36 PM

  • Single IDOC to Multiple Interface Mapping

    We have a requirement in our project where one masterdata IDOC will be sent from a SAP MDM box and will be transformed to a target IDOC and be sent to an SAP SNC box. However, the scenario is that depending on the contents of the IDOC, there can be multiple IDOCs that need to be created. For example, the single MDM IDOC has V1, V2 and V3 values then the IDOCS that should be sent to the SAP SNC box should be three.
    The IT head of the customer decided against using Enhanced Interface Determination (since the problem can be easily solved using a 1:n mapping) due to the complexity especially when the solution is rolled out to other regions as each region has it's own logic (currently, the other implementation has only 1:1 mapping so there is no problem). I had developed a 1:n mapping but the resulting map is too big and very complex.
    What I tried to do is to create separate mappings for each scenario that an IDOC needs to be generated out of the values from the received IDOC in XI and then define rules in the Interface Determination. Problem is that XI throws an error stating that multiple interfaces are found. So I cannot use Interface Determination to trigger creation of multiple IDOCS of the same type with different values from a single IDOC sent by the same SAP box.
    Question is, is there any way to solve this requirement without using Enhanced Receiver Determination. I was thinking of BPM but not really sure how to do it.
    Thanks in advance!
    Best Regards,
    Rommel Mendoza
    Hewlett Packard Asia-Pacific, Ltd.

    Thanks a lot for that.
    For example, We have this input Message:
    <ZMATMA>
      <IDOC>
        <E1MARAM>
           <E1MARMM>
               <MEINH>IT</MEINH>
           </E1MARMM>
           <E1MARMM>
               <MEINH>CS</MEINH>
           </E1MARMM>
           <E1MARMM>
               <MEINH>SW</MEINH>
           </E1MARMM>
        </E1MARAM>
      </IDOC>
    </ZMATMA>
    then there should be an output of:
    <SAVEMULTIPLE204>
      <IDOC>
        <BUOM>IT</BUOM>
      </IDOC>
    </SAVEMULTIPLE204>
    <SAVEMULTIPLE204>
      <IDOC>
        <BUOM>CS</BUOM>
      </IDOC>
    </SAVEMULTIPLE204>
    <SAVEMULTIPLE204>
      <IDOC>
        <BUOM>SW</BUOM>
      </IDOC>
    </SAVEMULTIPLE204>
    The logic is when the MEINH field of the ZMATMA02 IDOC has the values: IT, CS and SW, create one IDOC for each.
    Thanks in advance!
    Edited by: Rommel Mendoza on Nov 6, 2008 7:30 PM

  • Problem to analyse mapping error

    Hi all,
    I have a problem to analyse a BPM mapping error on PI7.1. The szenario is as follows: I have 3 different containers (Abstract Interfaces) which data is used to determine the content of a  result container.
    E.g:
    ABSTRACT_INTERFACE_1
    ABSTRACT_INTERFACE_2 -> Mapping -> ABSTRACT_RESULT_INTERFACE
    ABSTRACT_INTERFACE_3
    If have quouted the source interfaces (cardinality 1 for each interface)  in my operation mapping and configured the transformation step accordingly. The operation mapping alone works in the integration builder test environment. When I execute the BPM process, the mapping fails. Unfortunately the is no information in the trace leaf of the respective container information. Writing data to the mapping trace doesn't work neither.
    Has got anybody an idea what might be the problem?
    Kind regards,
    Heiko

    Hi Heiko,
    Pls, do the following:
    1. Build a java mapping which is going to write the payload content before the message mapping.
    import com.sap.aii.mapping.api.StreamTransformation;
    import com.sap.aii.mapping.api.StreamTransformationException;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.Map;
    public class InputFileWriter implements StreamTransformation {
        public void setParameter(Map map) {
        public void execute(InputStream in, OutputStream out)
        throws StreamTransformationException {
            try{
                File f=new File("C:\PayloadContent.xml");
                FileOutputStream fosPayload = new FileOutputStream(f);
                byte[] content= new byte[in.available()];
                int c;
                int i=0;
                String sb =  "";
                while ((c = in.read()) != -1){
                    content<i>=(byte)c;
                    sb += (char)content<i>;
                    i++;
                fosPayload.write(sb.getBytes());
                fosPayload.close();
                out.write(sb.getBytes());
                out.close();
            }catch(Exception ex){
                ex.printStackTrace();
    2. Add the javamapping to your interface mapping putting before of message mapping.
    3. Run your scenario.
    4. Check the file
    C:\PayloadContent.xml
    5. Test your message mapping in with PayloadContent.xml
    And tell me what happened.
    Regards
    Ivan
    Edited by: Jose Iván Reyes Arteaga on Jul 16, 2009 6:05 PM

Maybe you are looking for

  • Remote bootable hard drive & time machine

    can i use a remote hard drive with one partition for time machine, and another to make the drive bootable...

  • EXITS-PARAM in user exit

    Hi ,    When we do substitution in FICO by user exit there are three types of EXITS-PARAM     EXITS-PARAM = C_EXIT_PARAM_NONE.     EXITS-PARAM = C_EXIT_PARAM_FIELD     EXITS-PARAM = C_EXIT_PARAM_CLASS.    Could you tell me the difference among them?

  • User-defined http header and com.oracle.httpclient.HttpRequestBuilder

    Hello, In Java ME Embedded 8, I would like to send a HTTP request containing a user-defined identifier in the http header (X- header type), using the com.oracle.httpclient package.        HttpClient client = clientBuilder.build();         HttpRequest

  • Programs won't work ???

    Ok ... I have been using a Mac for years, and I know that every time a new OS update is released there are bound to be some problems, but I have never had problems with programs I bought a few weeks before the the OS update (let alone software that c

  • Internationalization in Portals

    Hi All, I am trying to do an application in Internationalization in portals. -> For that I have prepared the properties files and kept them in the dist\private\classes folder. -> Written the code for accessing the resource bundle by using getString()