View Javadoc

1   package org.opensync.engine.server.adapter;
2   
3   /***
4    * Title:       OpenSync
5    * Description: This class implements a part of the translation of the EDI X12
6    *              message 840 to XML.
7    *              The X12 EDI standard is the US standard for Edi.
8    *              An XML/EDI group has been formed to propose an XML DTD.
9    *              For more information, see http://www.xmledi-group.org
10   *              and http://www.eidx.org/publications/business_models
11   *              Description of the 840 message:
12   *              http://www.eidx.org/publications/guidelines/arq4010.pdf
13   */
14  
15  import java.io.BufferedReader;
16  import java.io.File;
17  import java.io.FileNotFoundException;
18  import java.io.FileReader;
19  import java.io.IOException;
20  import java.io.Reader;
21  import java.io.StreamTokenizer;
22  import java.io.StringReader;
23  import java.io.StringWriter;
24  import java.util.Vector;
25  
26  import javax.xml.parsers.ParserConfigurationException;
27  import javax.xml.parsers.SAXParser;
28  import javax.xml.parsers.SAXParserFactory;
29  
30  import org.opensync.engine.util.FileHelper;
31  import org.xml.sax.SAXException;
32  
33  class EdiAttributes {
34  
35        /****/
36        public String code;
37        /****/
38        public String name;
39        /****/
40        public boolean descriptor;
41  
42        /***
43         * @param	code
44         * @param	name
45         * @param	descriptor
46         */
47        public EdiAttributes(String code, String name, boolean descriptor) {
48          this.code = code;
49          this.name = name;
50          this.descriptor = descriptor;
51        }
52      };
53  
54  /***
55   * @author	xwarzee
56   */
57  public class EdiX128402Xml extends Translator {
58  
59    private DescriptorParser descriptorParser;
60    private int tok = -1;
61    private Vector header_elementNames = new Vector(16);
62    private Vector functional_elementNames = new Vector(8);
63    private Vector headingArea_elementNames = new Vector(2);
64    private Vector trailer_elementNames;
65  
66    /***/
67    /****/
68    public EdiX128402Xml() {
69  
70      header_elementNames.add(new EdiAttributes("I01", "Authorization Information Qualifier", true));
71      header_elementNames.add(new EdiAttributes("I02", "Authorization Information", false));
72      header_elementNames.add(new EdiAttributes("I03", "Security Inform Qualifier", true));
73      header_elementNames.add(new EdiAttributes("I04", "Security Information", false));
74      header_elementNames.add(new EdiAttributes("I05", "Interchange ID Qualifier", true));
75      header_elementNames.add(new EdiAttributes("I06", "Interchange Sender ID", false));
76      header_elementNames.add(new EdiAttributes("I05", "Interchange ID Qualifier", true));
77      header_elementNames.add(new EdiAttributes("I07", "Interchange Receiver ID", false));
78      header_elementNames.add(new EdiAttributes("I08", "Interchange Date", false));
79      header_elementNames.add(new EdiAttributes("I09", "Interchange Time", false));
80      header_elementNames.add(new EdiAttributes("I10", "Interchange Control Standards", true));
81      header_elementNames.add(new EdiAttributes("I11", "Interchange Control Version", false));
82      header_elementNames.add(new EdiAttributes("I12", "Interchange Control Number", false));
83      header_elementNames.add(new EdiAttributes("I13", "Acknowledgment Requested", true));
84      header_elementNames.add(new EdiAttributes("I14", "Test Indicator", true));
85      header_elementNames.add(new EdiAttributes("I15", "Subelement Separator", false));
86  
87      functional_elementNames.add(new EdiAttributes("479", "Functional Identifier Code", true));
88      functional_elementNames.add(new EdiAttributes("142", "Application Senders Code", false));
89      functional_elementNames.add(new EdiAttributes("124", "Application Receivers Code", true));
90      functional_elementNames.add(new EdiAttributes("373", "Date", false));
91      functional_elementNames.add(new EdiAttributes("337", "Time", false));
92      functional_elementNames.add(new EdiAttributes("I12", "Group Control", false));
93      functional_elementNames.add(new EdiAttributes("455", "Responsability Agency Code", true));
94      functional_elementNames.add(new EdiAttributes("480", "Version Release Industry", false));
95  
96      headingArea_elementNames.add(new EdiAttributes("143", "Transaction Set Identifier Code", true));
97      headingArea_elementNames.add(new EdiAttributes("329", "Transaction Set Control Number", false));
98      headingArea_elementNames.add(new EdiAttributes("353", "Transaction Set Purpose Code", true));
99      headingArea_elementNames.add(new EdiAttributes("586", "Request for Quote Reference Number", false));
100     headingArea_elementNames.add(new EdiAttributes("373", "Date", false));
101     headingArea_elementNames.add(new EdiAttributes("374", "Date/Time Qualifier", true));
102     headingArea_elementNames.add(new EdiAttributes("373", "Date", false));
103   }
104 
105   /***
106    * @param	descriptorFileName
107    * @exception	IOException
108    * @exception	FileNotFoundException
109    * @exception	SAXException
110    * @exception	ParserConfigurationException
111    */
112   public void readDescriptor(String descriptorFileName)
113   throws ParserConfigurationException, SAXException,FileNotFoundException,IOException {
114     descriptorParser = new DescriptorParser(this);
115 
116     SAXParserFactory factory = SAXParserFactory.newInstance();
117     factory.setValidating(true);
118     SAXParser parser = factory.newSAXParser();
119     parser.parse( new File(descriptorFileName).toURL().toExternalForm(),
120                   descriptorParser);
121   }
122 
123   private boolean  buildHeader(StreamTokenizer st, StringWriter fw) throws IOException {
124      boolean tokenWasDelimiter = false;
125 
126     if (!st.sval.equals("ISA")) return false;
127 
128     //System.out.println("begin buildHeader");
129 
130     int i = 1;
131     String descriptor = "";
132     while (st.ttype != StreamTokenizer.TT_EOF && i < 16)
133     {
134       // We're not at EOF
135       while (st.ttype != StreamTokenizer.TT_EOL &&
136              st.ttype != StreamTokenizer.TT_EOF)
137       {
138         if (st.ttype != StreamTokenizer.TT_EOL &&
139                  st.ttype != StreamTokenizer.TT_EOF)
140         {
141           if (tok == StreamTokenizer.TT_WORD && st.sval != null) {
142               if (st.sval.equals("ISA")) {
143                 fw.write("<segment code=\"ISA\" name=\"Interchange Control Header\">");
144               } else {
145                 fw.write("<element code=\"" + ((EdiAttributes)header_elementNames.get(i-1)).code + "\" name=\""
146                           +((EdiAttributes)header_elementNames.get(i-1)).name + "\">");
147 
148                 if (((EdiAttributes)header_elementNames.get(i-1)).descriptor)
149                   descriptor="descriptor=\"" + st.sval + "\"";
150                 else
151                   descriptor="";
152                 if (!st.sval.trim().equals("")) {
153                   if (st.sval.trim().equals("<"))
154                     fw.write("  <value>&lt;</value>");
155                   else
156                     fw.write("  <value " + descriptor + ">" + st.sval + "</value>");
157                   }
158                 else
159                   fw.write("<value/>");
160                 fw.write("</element>");
161                 i++;
162               }
163               //System.out.println("token: " + st.sval.trim());
164               tokenWasDelimiter = false;
165           }
166           else  if (tok == '*' && tokenWasDelimiter) {
167             fw.write(" ");
168           } else if (tok == '*')
169             tokenWasDelimiter = true;
170         }
171         tok = st.nextToken();
172       }
173       tok = st.nextToken();
174     }
175     fw.write("</segment>");
176 
177     //System.out.println("begin buildHeader");
178 
179     return true;
180   }
181 
182   private boolean  buildFunctionalGroup(StreamTokenizer st, StringWriter fw) throws IOException {
183 
184     boolean tokenWasDelimiter = false;
185     boolean status = false;
186 
187     //System.out.println("begin buildFunctionalGroup");
188 
189     if (!st.sval.equals("GS")) return false;
190 
191     int i = 1;
192     String descriptor = "";
193     while (st.ttype != StreamTokenizer.TT_EOF && i < 8)
194     {
195       // We're not at EOF
196       while (st.ttype != StreamTokenizer.TT_EOL &&
197              st.ttype != StreamTokenizer.TT_EOF)
198       {
199         if (st.ttype != StreamTokenizer.TT_EOL &&
200                  st.ttype != StreamTokenizer.TT_EOF)
201         {
202           if (tok == StreamTokenizer.TT_WORD && st.sval != null) {
203               if (st.sval.equals("GS")) {
204                 fw.write("<functionalgroup>");
205                 fw.write("<segment code=\"GS\" name=\"Functional Group Header\">");
206               } else {
207                 fw.write("<element code=\"" + ((EdiAttributes)functional_elementNames.get(i-1)).code + "\" name=\""
208                           +((EdiAttributes)functional_elementNames.get(i-1)).name + "\">");
209 
210                 if (((EdiAttributes)functional_elementNames.get(i-1)).descriptor)
211                   descriptor="descriptor=\"" + st.sval + "\"";
212                 else
213                   descriptor="";
214                 if (!st.sval.trim().equals("")) {
215                   if (st.sval.trim().equals("<"))
216                     fw.write("  <value>&lt;</value>");
217                   else
218                     fw.write("  <value " + descriptor + ">" + st.sval + "</value>");
219                   }
220                 else
221                   fw.write("<value/>");
222                 fw.write("</element>");
223                 i++;
224               }
225               //System.out.println("token: " + st.sval.trim());
226               tokenWasDelimiter = false;
227           }
228           else  if (tok == '*' && tokenWasDelimiter) {
229             fw.write(" ");
230           } else if (tok == '*')
231             tokenWasDelimiter = true;
232         }
233         tok = st.nextToken();
234       }
235       tok = st.nextToken();
236     }
237     fw.write("</segment>");
238     status = buildTransaction(st, fw);
239     fw.write("</functionalgroup>");
240 
241     //System.out.println("end buildFunctionalGroup");
242     return status;
243   }
244 
245    private boolean buildHeadingArea(StreamTokenizer st, StringWriter fw) throws IOException {
246 
247     boolean tokenWasDelimiter = false;
248 
249     if (!st.sval.equals("ST")) return false;
250 
251     //System.out.println("  begin buildHeadingArea");
252 
253     int i = 1;
254     String descriptor = "";
255     while (st.ttype != StreamTokenizer.TT_EOF && i < 8 && !st.sval.equals("PO1"))
256     {
257       // We're not at EOF
258       while (st.ttype != StreamTokenizer.TT_EOL &&
259              st.ttype != StreamTokenizer.TT_EOF)
260       {
261         if (st.ttype != StreamTokenizer.TT_EOL &&
262                  st.ttype != StreamTokenizer.TT_EOF)
263         {
264           if (tok == StreamTokenizer.TT_WORD && st.sval != null) {
265               if (st.sval.equals("ST")) {
266                 fw.write("<table section=\"header\">");
267                 fw.write("<segment code=\"" +st.sval+ "\" name=\"Transaction Set Header\">");
268               } else if (st.sval.equals("BQT")) {
269                 fw.write("</segment>");
270                 fw.write("<segment code=\"" +st.sval+ "\" name=\"Beginning Segment for Request for Quotation\">");
271               } else {
272                 fw.write("<element code=\"" + ((EdiAttributes)headingArea_elementNames.get(i-1)).code + "\" name=\""
273                           +((EdiAttributes)headingArea_elementNames.get(i-1)).name + "\">");
274 
275                 if (((EdiAttributes)headingArea_elementNames.get(i-1)).descriptor)
276                   descriptor="descriptor=\"" + st.sval + "\"";
277                 else
278                   descriptor="";
279                 if (!st.sval.trim().equals("")) {
280                   if (st.sval.trim().equals("<"))
281                     fw.write("  <value>&lt;</value>");
282                   else
283                     fw.write("  <value " + descriptor + ">" + st.sval + "</value>");
284                   }
285                 else
286                   fw.write("<value/>");
287                 fw.write("</element>");
288                 i++;
289               }
290               //System.out.println("token: " + st.sval.trim());
291               tokenWasDelimiter = false;
292           }
293           else  if (tok == '*' && tokenWasDelimiter) {
294             fw.write(" ");
295           } else if (tok == '*')
296             tokenWasDelimiter = true;
297         }
298         tok = st.nextToken();
299       }
300       tok = st.nextToken();
301     }
302     fw.write("</segment>");
303     fw.write("</table>");
304 
305     //System.out.println("  end buildHeadingArea");
306     return true;
307    }
308 
309    private boolean buildItems(StreamTokenizer st, StringWriter fw) throws IOException {
310 
311     //System.out.println("  begin buildItems");
312     //System.out.println("  end buildItems");
313 
314     return true;
315    }
316    private boolean buildSummaryArea(StreamTokenizer st, StringWriter fw) throws IOException {
317 
318     //System.out.println("  begin buildSummaryArea");
319     //System.out.println("  end buildSummaryArea");
320 
321     return true;
322    }
323 
324   private boolean  buildTransaction(StreamTokenizer st, StringWriter fw) throws IOException {
325 
326     boolean status = false;
327 
328     //System.out.println("begin buildTransaction");
329 
330     if (st.sval.equals("ST")) {
331       fw.write("<transactionset code=\"840\" name=\"Request for Quotation\">");
332       status = buildHeadingArea(st, fw);
333       if (status) status = buildItems(st, fw);
334       if (status) status = buildSummaryArea(st, fw);
335       fw.write("</transactionset>");
336     } else
337       status=false;
338     //System.out.println("end buildTransaction");
339     return status;
340   }
341 
342   private boolean  buildTrailer(StreamTokenizer st, StringWriter fw) {
343 
344     //System.out.println("begin buildTrailer");
345     //System.out.println("end buildTrailer");
346 
347     return true;
348   }
349 
350   /***
351    * @param	input
352    * @exception	IOException
353    */
354   public String parse(Reader input)
355    throws java.io.IOException
356 
357   {
358     BufferedReader br = new BufferedReader(input);
359 
360     if (skipfirstlines > 0) {
361       int linesToSkip = skipfirstlines;
362       while (linesToSkip > 0) {
363         br.readLine();
364         linesToSkip--;
365       }
366     }
367     StreamTokenizer st = new StreamTokenizer(br);
368     st.resetSyntax();
369     st.wordChars('0', '9');
370     st.wordChars('a', 'z');
371     st.wordChars('A', 'Z');
372     st.wordChars(128 + 32, 255);
373     st.wordChars('!','@');
374     st.wordChars(' ', ' ');
375 
376 
377     if (!suppressquotes) {
378       // keep quotes in the output
379       st.wordChars('"', '"');
380       st.wordChars('\'', '\'');
381     } else {
382       // double or simple quotes eliminated
383       // in the output
384       st.quoteChar('"');
385       st.quoteChar('\'');
386     }
387 
388     // Default constructor whitespaceChars(0, ' ')
389     //st.whitespaceChars(' ', ' ');
390     // st.commentChar('/');
391 
392     //st.parseNumbers();
393 
394     // We want to read the file one line at a time, so end-ofline matters
395     st.eolIsSignificant(true);
396     // The delimiter between fields is a comma, not a space
397     //st.whitespaceChars((int)delimiter.charAt(0), (int)delimiter.charAt(0));
398     // In order to compute the special case:
399     // a||b|c where | is the current delimiter.
400     // The delimiter will be return has a token.
401     //st.ordinaryChar((int)delimiter.charAt(0));
402     // In an EDI X12 message, the separator is '*'
403     st.ordinaryChar('*');
404     //FileWriter fw = new FileWriter(outputFile);
405     StringWriter fw = new StringWriter();
406 
407     // Write the XML declaration and the root element
408     fw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
409     fw.write("<!DOCTYPE envelope SYSTEM \"edi_X12_envelope.dtd\">");
410     fw.write("<envelope format=\"X12\">\n");
411 
412     tok = st.nextToken();
413 
414     buildHeader(st, fw);
415     buildFunctionalGroup(st, fw);
416     buildTrailer(st,fw);
417 /*
418     boolean tokenWasDelimiter = false;
419 
420     int tok;
421     // Get the first token, then check its type
422     tok = st.nextToken();
423     while (st.ttype != StreamTokenizer.TT_EOF)
424     {
425       // We're not at EOF
426       while (st.ttype != StreamTokenizer.TT_EOL &&
427              st.ttype != StreamTokenizer.TT_EOF)
428       {
429         if (st.ttype != StreamTokenizer.TT_EOL &&
430                  st.ttype != StreamTokenizer.TT_EOF)
431         {
432           if (tok == StreamTokenizer.TT_WORD && st.sval != null) {
433               fw.write(st.sval.trim());
434               System.out.println("token: " + st.sval.trim());
435               tokenWasDelimiter = false;
436           }
437           else  if (tok == '*' && tokenWasDelimiter) {
438             fw.write(" ");
439           } else if (tok == '*')
440             tokenWasDelimiter = true;
441         }
442         tok = st.nextToken();
443       }
444       tok = st.nextToken();
445     }
446 */
447     // Now we're at the end of the file, so close the XML Data,
448     // flush the buffer to disk, and close the newly-created file.
449     fw.write("</envelope>\n");
450     fw.flush();
451     fw.close();
452     return fw.toString();
453   }
454 
455   /***
456    * @param	txt
457    * @exception	SAXException
458    * @exception	IOException
459    * @exception	ParserConfigurationException
460    */
461   public String parseTxt(String txt)
462     throws java.io.IOException, SAXException, ParserConfigurationException
463   {
464     StringReader input = new StringReader(txt);
465     return parse(input);
466 
467   }
468 
469    /***
470     * @param	argv
471     * @exception	SAXException
472     * @exception	IOException
473     * @exception	ParserConfigurationException
474     */
475    public static void main(String argv[])
476     throws java.io.IOException, SAXException, ParserConfigurationException
477   {
478 
479      String fileSeparator = System.getProperty("file.separator");
480      String configFolder = System.getProperty("opensync.configfolder");
481      configFolder = (configFolder == null ? "" : configFolder);
482 
483      String fullDescriptorFileName = System.getProperty("opensync.home") +
484                                     fileSeparator+ "etc"+fileSeparator+configFolder+fileSeparator+"descript"+fileSeparator +
485                                     argv[0];
486 
487     FileReader input = null;
488 
489     if (argv.length == 3)
490     {
491       EdiX128402Xml cp = new EdiX128402Xml();
492       try {
493         cp.readDescriptor(fullDescriptorFileName);
494       } catch (Exception e) {
495         System.err.println("Exception caught: " + e.getMessage());
496       }
497 
498       try {
499         input = new FileReader(argv[1]);
500         cp.saveString(argv[2], cp.parse(input));
501       }
502       catch (IOException e) {
503         System.err.println("Exception caught: " + e.getMessage());
504       }
505       finally {
506         if (input != null) {
507           input.close();
508           input = null;
509         }
510       }
511     } else {
512           System.out.println("\nUsage: java EdiX128402Xml configFile.xml csv-file xml-file");
513           System.out.println("       where csv-file is the comma-separated file, and ");
514           System.out.println("       xml-file is the XML file to be generated.");
515     }
516   }
517 
518     /***
519    * @param	filename
520    * @param	string
521    * @exception	IOException
522    */
523   public void saveString(String filename, String string) throws IOException {
524     FileHelper.stringToFile(string,filename);
525   }
526 }