midrange.com code scratchpad
Name:
RDi LPEX action ConvertFixedToFreeAction
Scriptlanguage:
Java
Tabwidth:
4
Date:
02/18/2016 01:17:24 pm
IP:
Logged
Description:
Convert fixed form RPG to free format RPG. Place the cursor on a spec, then action f2f (or whatever you name the action). This will convert the spec to fully free and insert the new code beneath the existing code so you can compare. This is an early version. Handles D, P, and H specs.
--buck
Code:
  1. package com.kc2hiz.lpexextensions; 
  2.  
  3. import com.ibm.lpex.core.LpexAction;
  4.  
  5. import com.ibm.lpex.core.LpexView;
  6. import com.ibm.lpex.core.LpexLog;
  7. import java.util.ArrayList;
  8. import java.util.regex.Pattern;
  9. import java.util.regex.Matcher;
  10.  
  11. /**
  12.  * Convert Fixed-specification to fully free format
  13.  * <p>Intended to convert one spec at a time to allow for easier review of the conversion.
  14.  * <p>for use as an Lpex User Action.
  15.  * @author buck
  16.  * @version 01.00.00 Initial
  17.  * @version 01.00.01 Add H-spec
  18.  *
  19.  */ 
  20. public class ConvertFixedToFreeAction implements LpexAction {
  21.     
  22.     /**
  23.      * Check to see if we should be allowed to perform the D to free conversion
  24.      * @param view LpexView to operate on
  25.      * @return true if action is available for this view
  26.      * @see com.ibm.lpex.core.LpexAction#available(com.ibm.lpex.core.LpexView)
  27.      */
  28.     @Override
  29.     public boolean available(LpexView view) {
  30.           return view.currentElement() > 0 &&
  31.                      !view.queryOn("readonly"); /* &&
  32.                      view.queryOn("block.anythingSelected"); */
  33.     }
  34.  
  35.     /**
  36.      * Converts fixed specifications to fully free
  37.      * @param view LpexView to operate on
  38.      * @see com.ibm.lpex.core.LpexAction#doAction(com.ibm.lpex.core.LpexView)
  39.      */
  40.     @Override
  41.     public void doAction(LpexView view) {
  42.         
  43.         // work with the line the cursor is on
  44.         int thisLine = view.currentElement();
  45.         String sourceStmt = view.elementText(thisLine);
  46.  
  47.         // leave if no text
  48.         if (sourceStmt.length() == 0) {
  49.             view.doCommand("set messageText Empty text");            
  50.             return;
  51.         }
  52.  
  53.         // need to at least see 6 columns or we don't possibly have a d-spec
  54.         if (sourceStmt.length() <= 5) {
  55.             view.doCommand("set messageText Line too short");
  56.             return;
  57.         }
  58.  
  59.         // one routine for each spec we're dealing with
  60.         String specType = getSpecFromText(sourceStmt);
  61.         
  62.         switch (specType) {
  63.             case "h":
  64.                 hToFree(view, sourceStmt, thisLine);
  65.                 break;
  66.             case "d":
  67.                 dToFree(view, sourceStmt, thisLine);
  68.                 break;
  69.             case "p":
  70.                 dToFree(view, sourceStmt, thisLine);
  71.                 break;
  72.             default:
  73.                 view.doCommand("set messageText specType is" + specType);
  74.                 break;
  75.         }
  76.         
  77.         return;
  78.     }
  79.     
  80.  
  81.     
  82.     // handle converting D-specs to fully free
  83.     private void dToFree(LpexView view, String sourceStmt, int thisLine) {
  84.         // Instantiate a DSpec object.  The constructor will break out the columns.
  85.         DSpec dspec = new DSpec(view, sourceStmt, thisLine);
  86.  
  87.         // leave if we're not looking at a D- or P-specification
  88.         if (!dspec.spec.equals("d") && 
  89.                 !dspec.spec.equals("p")) {
  90.             view.doCommand("set messageText Not a D- or P-spec");            
  91.             return;
  92.         }
  93.         
  94.         // Handle the various definition types we know about
  95.         if (dspec.spec.equals("d") || dspec.spec.equals("p")) {
  96.             if (dspec.defType.trim().equals("b") ||
  97.                     dspec.defType.trim().equals("c") ||
  98.                     dspec.defType.trim().equals("e") ||
  99.                     dspec.defType.equals("ds") ||
  100.                     dspec.defType.equals("pi") ||
  101.                     dspec.defType.equals("pr") ||
  102.                     dspec.defType.trim().equals("s")) {
  103.                 convertSubfieldsToFree(view, dspec);
  104.                 // position the cursor to the top of the area we converted from
  105.                 view.doDefaultCommand("locate element " + thisLine);
  106.                 view.doDefaultCommand("set position 1");
  107.             } else {
  108.                 view.doCommand("set messageText Unusable D-spec. In the middle of a structure? " + dspec.defType);
  109.             }    
  110.         }
  111.  
  112.     }
  113.  
  114.  
  115.     // handle converting H-specs to fully free
  116.     private void hToFree(LpexView view, String sourceStmt, int thisLine) {
  117.         // Instantiate a DSpec object.  The constructor will break out the columns.
  118.         HSpec hspec = new HSpec(view, sourceStmt, thisLine);
  119.  
  120.         int lastSubfieldNumber = view.currentElement();    
  121.         ArrayList<String> dsLines = new ArrayList<String>();
  122.         String dsDclTemp = "";
  123.                 
  124.         dsDclTemp = "       ctl-opt";
  125.                 
  126.         // if there are keywords, append them
  127.         if (hspec.keywords.length() != 0) {
  128.             dsDclTemp = dsDclTemp.concat(" " + hspec.keywords);
  129.         }
  130.  
  131.         // append the semicolon
  132.         dsDclTemp = dsDclTemp.concat(";");
  133.  
  134.         // right hand comments (if any) come after the semicolon
  135.         if (hspec.rhComment.length() != 0) {
  136.             dsDclTemp = dsDclTemp.concat(" // " + hspec.rhComment);
  137.         }
  138.         
  139.         // now that we have a fully formed line, add it to the array of lines
  140.         dsLines.add(dsDclTemp);
  141.  
  142.         // position cursor AFTER the block we just read
  143.         view.doCommand("locate line " + (lastSubfieldNumber));
  144.         
  145.         // loop through the array and write the contents out
  146.         for (String dsLine: dsLines) {
  147.             if (!dsLine.isEmpty()) {
  148.                 view.doDefaultCommand("insert " + dsLine);
  149.             }
  150.         }
  151.         
  152.         // re-position the cursor to the top of the area we converted from
  153.         view.doDefaultCommand("locate element " + thisLine);
  154.         view.doDefaultCommand("set position 1");
  155.         
  156.     }    
  157.  
  158.  
  159.  
  160.     /**
  161.      * Convert one or more field definitions from fixed to free
  162.      * If a standalone or constant, converts just the one line
  163.      * If a DS, PI or PR, converts the entire structure
  164.      * @param view LpexView - the current view we're working on
  165.      * @param dspec String - the first line of the structure (DS, PR, PI)
  166.      */
  167. private void convertSubfieldsToFree(LpexView view, DSpec dspec) {
  168.         int e = 0;
  169.         int lastSubfieldNumber = view.currentElement();    
  170.         int specLineNumber = view.currentElement();    
  171.         String dsTemp = "";
  172.         ArrayList<String> dsLines = new ArrayList<String>();
  173.         String dsDclTemp = "";
  174.                 
  175.         // the declare uses the definition type
  176.         // unless b, which is a P-spec and s/b 'proc'
  177.         // unless e, which gets nothing for the declaration
  178.         if (!dspec.defType.trim().equals("e")) {
  179.             if (!dspec.defType.trim().equals("b")) {
  180.                 dsDclTemp = "       dcl-" + dspec.defType.trim() + " "    + dspec.name;
  181.             } else {
  182.                 dsDclTemp = "       dcl-proc " + dspec.name;
  183.             }
  184.                 
  185.             // if there is a datatype, append it
  186.             String subfieldDataType = getDataTypeKeyword(dspec.fromPos, dspec.len, dspec.dataType, dspec.decimals, dspec.keywords);
  187.             if (subfieldDataType.length() != 0) {
  188.                 dsDclTemp = dsDclTemp.concat(" " + subfieldDataType);
  189.             }
  190.  
  191.             // if there are keywords, append them
  192.             // first, strip out procptr
  193.             if (dspec.keywords.length() != 0) {
  194.                 dspec.keywords = dspec.keywords.replace("procptr", "");
  195.                 dsDclTemp = dsDclTemp.concat(" " + dspec.keywords);
  196.             }
  197.  
  198.             // append the semicolon
  199.             dsDclTemp = dsDclTemp.concat(";");
  200.  
  201.             // right hand comments (if any) come after the semicolon
  202.             if (dspec.rhComment.length() != 0) {
  203.                 dsDclTemp = dsDclTemp.concat(" // " + dspec.rhComment);
  204.             }
  205.         
  206.             // now that we have a fully formed line, add it to the array of lines
  207.             dsLines.add(dsDclTemp);
  208.         }
  209.  
  210.         
  211.         // loop forward through the next set of source lines
  212.         // until the end of the structure is found
  213.         // note that for standalone and constant lines, the very next spec terminates the 'structure'
  214.         for (e = specLineNumber + 1; e <= view.elements(); e++) {
  215.             
  216.             String dsSubfield = view.elementText(e);
  217.             
  218.             // if blank line, assume end of struc
  219.             int textLengthDS = dsSubfield.length();
  220.             if (textLengthDS == 0) {
  221.                 break;
  222.             }
  223.  
  224.             // need to at least see 6 columns or we don't possibly have a d-spec
  225.             if (textLengthDS <= 5) {
  226.                 break;
  227.             } 
  228.  
  229.             // make a new DSpec object which will break out the columns
  230.             DSpec subfield = new DSpec(view, dsSubfield, e);
  231.  
  232.             // comments have no fields to parse, but  
  233.             // carry the comments forward into the converted block
  234.             if (subfield.isComment) {
  235.                 dsTemp = "       // " + subfield.longComment.trim();
  236.             } else {
  237.                 
  238.                 // read the next line if this one is a continuation
  239.                 if (dsSubfield.matches(".*\\.\\.\\.")) {
  240.                     continue;
  241.                 }
  242.  
  243.                 // leave the loop if we've reached the end of the subfields
  244.                 if (subfield.spec.equals("d") && !subfield.defType.equals("  ")) {
  245.                     break;
  246.                 }
  247.  
  248.                 // leave if we're not looking at a D-specification
  249.                 if (!subfield.spec.equals("d")) {
  250.                     break;
  251.                 }
  252.  
  253.                 // now generate the keywords for data type
  254.                 String dataTypeKwdDS = getDataTypeKeyword(subfield.fromPos, subfield.len, subfield.dataType, subfield.decimals, subfield.keywords);
  255.  
  256.                 dsTemp =  "         " + 
  257.                         subfield.name + " " + dataTypeKwdDS;
  258.                 // keywords are optional; don't leave a trailing space if none needed
  259.                 // also, strip procptr
  260.                 if (subfield.keywords.length() != 0) {
  261.                     subfield.keywords = subfield.keywords.replace("procptr", "");
  262.                     dsTemp = dsTemp.concat(" " + subfield.keywords);
  263.                 }
  264.  
  265.                 // add the terminating semicolon
  266.                 dsTemp = dsTemp.concat(";");
  267.  
  268.                 // if we have a right hand comment, carry it forward
  269.                 if (subfield.rhComment.length() != 0) {
  270.                     dsTemp = dsTemp.concat(" // " + subfield.rhComment.trim());
  271.                 }
  272.                 
  273.                 // save the element number of the last subfield we actually processed
  274.                 lastSubfieldNumber = e;
  275.             }
  276.             dsLines.add(dsTemp);
  277.             
  278.         };
  279.         
  280.         // ...and the end
  281.         // not needed for standalone and constant
  282.         if (!dspec.defType.trim().equals("c") && 
  283.             !dspec.defType.trim().equals("s") &&
  284.             !dspec.defType.trim().equals("b") &&
  285.             !dspec.defType.trim().equals("p")) {
  286.             
  287.             String endDsTemp = "";
  288.             // the declare uses the definition type
  289.             // unless b/e, which are P-specs and s/b 'proc'
  290.             if (!dspec.defType.trim().equals("e")) {
  291.                 endDsTemp = "       end-"  + dspec.defType + ";";
  292.             } else {
  293.                 endDsTemp = "       end-proc;";
  294.             }
  295.             
  296.             dsLines.add(endDsTemp);
  297.         }
  298.  
  299.         // position cursor AFTER the block we just read
  300.         view.doCommand("locate line " + (lastSubfieldNumber));
  301.         
  302.         // loop through the array and write the contents out
  303.         for (String dsLine: dsLines) {
  304.             if (!dsLine.isEmpty()) {
  305.                 view.doDefaultCommand("insert " + dsLine);
  306.             }
  307.         }
  308.     }
  309.  
  310.  
  311. /**
  312.  * build up the data type keyword based on the data type
  313.  * @param fromPos String
  314.  * @param len String
  315.  * @param dataType String
  316.  * @param decimals String
  317.  * @param keywords String
  318.  * @return dataTypeKwd String
  319.  */
  320. private String getDataTypeKeyword(String fromPos, String len, String dataType, String decimals, String keywords) {
  321.     String dataTypeKwd = "";
  322.     int tempLen = 0;
  323.  
  324.     // the data type can be blank and the RPG compiler will
  325.     // supply a rational default.  We need to do the same thing.
  326.     // note that pointer data types have no length
  327.     if (len.length() != 0 && dataType != "*") {
  328.         if (dataType.length() == 0) {
  329.             if (decimals.length() == 0) {
  330.                 dataType = "a";
  331.             } else {
  332.                 dataType = "p";
  333.             }
  334.         }
  335.     }
  336.  
  337.     // have a length adjustment.  No data type keyword for this.
  338.     // instead, append the adjustment to the LIKE keyword
  339.     // in the getKeywordsFromText method
  340.     if (!len.matches(".*\\+.*")) {
  341.         // old style from/to specs
  342.         // convert length 
  343.         String tempLenChar = len;
  344.         if (fromPos.length() != 0) {
  345.             tempLen = Integer.parseInt(len) - Integer.parseInt(fromPos) + 1;
  346.             tempLenChar = String.valueOf(tempLen);
  347.         }
  348.  
  349.         // data type
  350.         switch (dataType) {
  351.         case "":    // data structures
  352.             dataTypeKwd = "";
  353.             break;
  354.         case "a":
  355.             dataTypeKwd = "char(" + tempLenChar + ")";
  356.             break;
  357.         case "f":
  358.             dataTypeKwd = "float(" + tempLenChar + ")";
  359.             break;
  360.         case "i":
  361.             dataTypeKwd = "int(" + tempLenChar + ")";
  362.             break;
  363.         case "n":
  364.             dataTypeKwd = "ind";
  365.             break;
  366.         case "p":
  367.             dataTypeKwd = "packed(" + tempLenChar + ": " + decimals + ")";
  368.             break;
  369.         case "s":
  370.             dataTypeKwd = "zoned(" + tempLenChar + ": " + decimals + ")";
  371.             break;
  372.         case "u":
  373.             dataTypeKwd = "uns(" + tempLenChar + ")";
  374.             break;
  375.         case "*":
  376.             // the procptr keyword becomes pointer(*proc)
  377.             int i = keywords.indexOf("procptr");
  378.             String procKwd = "";
  379.             if (i != -1) {
  380.                 procKwd = "(*proc)";
  381.             }
  382.             dataTypeKwd = "pointer" + procKwd;
  383.             break;
  384.         default:
  385.             dataTypeKwd = "unk(" + dataType + ") tempLenChar("
  386.                     + tempLenChar + ")";
  387.             break;
  388.         }
  389.  
  390.         // we may have an old style from-to situation
  391.         // use the POS keyword to tell the compiler where the subfield starts
  392.         if (fromPos.length() != 0) {
  393.             dataTypeKwd = dataTypeKwd.concat(" pos(" + fromPos + ")");
  394.         }
  395.     }
  396.  
  397.     return dataTypeKwd;
  398. }
  399.  
  400. //utility methods
  401. /**
  402. * Extract RPG specification type (D, P, C, F) from a line of source code
  403. * @param sourceStmt String raw text
  404. * @return spec String lower case spec (c, d, f, p, etc.)
  405. */
  406. String getSpecFromText(String sourceStmt) {
  407.     String spec = "";
  408.     
  409.     if (sourceStmt.length() > 5) {
  410.         spec = sourceStmt.substring(5, 6).toLowerCase();
  411.     }
  412.     return spec;
  413. }
  414.  
  415.  
  416. /**
  417. * is this entire spec a comment line?
  418. * @param sourceStmt String - raw D-specification
  419. * @param d DSpec - the parsed d-spec object
  420. * @return true if entire line is a comment
  421. */
  422. boolean isComment(String sourceStmt) {
  423. boolean isComment = false;
  424.  
  425. if (sourceStmt.length() >= 8) {
  426.  
  427.     // comments can be either a * in column 7 or
  428.     // a pair of slashes preceded by white space
  429.     // the first is easy:
  430.     if (sourceStmt.substring(6, 7).equals("*")) {
  431.         isComment = true;
  432.     }
  433.  
  434.     // the second is a bit harder: 
  435.     if (sourceStmt.matches(".{5} *//.*")) {
  436.         isComment = true;
  437.     }
  438. }
  439. return isComment;
  440. }
  441.  
  442. /**
  443. * extract comment from a comment line
  444. * @param sourceStmt String - raw D-specification
  445. * @return comment String
  446. */
  447. String getComment(String sourceStmt) {
  448. String comment = "";
  449.  
  450. if (isComment(sourceStmt)) {
  451.  
  452.     // comments can be either a * in column 7 or
  453.     // a pair of slashes preceded by white space
  454.     // the first is easy:
  455.     if (sourceStmt.substring(6, 7).equals("*")) {
  456.         comment = sourceStmt.substring(8, sourceStmt.length());
  457.     }
  458.  
  459.     // the second is a bit harder: 
  460.     if (sourceStmt.matches(".{5} *//.*")) {
  461.         String[] parts = sourceStmt.split(".{5} *//");
  462.         comment = parts[1];
  463.     }
  464. }
  465. return comment;
  466. }
  467.  
  468.  
  469. /**
  470. * Extract right hand comment from raw d-spec
  471. * @param sourceStmt String raw d-spec
  472. * @return rhComment String right-hand comment
  473. */
  474. String getRhCommentFromText(String sourceStmt) {
  475. String rhComment = "";
  476.  
  477. if (sourceStmt.length() > 81) {
  478.     int i = 100;
  479.     if (sourceStmt.length() <= i) {
  480.         i = sourceStmt.length();
  481.     }
  482.     rhComment = sourceStmt.substring(80, i).trim();
  483. }
  484. return rhComment;
  485. }
  486.  
  487. /**
  488. * Log debugging text to the error log
  489. * @param message String 
  490. */
  491. void log(String message) {
  492. final boolean DEBUG = false;
  493.  
  494. if (DEBUG) {
  495.     LpexLog.log(message);
  496. }    
  497.  
  498.  
  499. }
  500.  
  501.  
  502. /**
  503. * This stores the various column based fields for an h-spec
  504. * This object tokenises the line with the definitions.  It will also move backward 
  505. * in the view's text lines to accumulate names continued from earlier lines.
  506. * @param view LpexView 
  507. * @param dSpec String a single raw d-spec (field / subfield)
  508. * @author buck
  509. *
  510. */
  511. class HSpec {
  512. public String spec = "";
  513. public String keywords = "";
  514. public String rhComment = "";
  515. public boolean isComment = false;
  516. public String longComment = "";
  517.  
  518. // constructor
  519. public HSpec(LpexView view, String sourceStmt, int thisLine) {
  520.     
  521.     // I prefer lower case, so everything except the name will be monocased
  522.     // RDi trims each line, so they don't all equal 100 bytes...
  523.     // must test for out of bounds before substringing!
  524.     
  525.     /*
  526.      *  1 -  5 sequence number / text
  527.      *  6 -  6 hSpec 
  528.      *  7 - 80 keywords
  529.      * 81 -100 comment
  530.      * 
  531.      * Alternatively, there can be a comment of the form:
  532.      *  6 -  6 hSpec 
  533.      *  7 -  7 *
  534.      *  8 -100 comment
  535.      *  
  536.      * Alternatively, there can be a comment of the form:  
  537.      * 6 -  7 blanks
  538.      * 8 -100 // comment.  Note that there can be any number of blanks 
  539.      *                     preceding the //.
  540.      *                     
  541.      * Alternatively, there can be a continuation line of the form:
  542.      * 6 -  6 d
  543.      * 7 - 80 someName...                     
  544.      * 
  545.      */
  546.         
  547.     spec = getSpecFromText(sourceStmt);
  548.     
  549.     isComment = isComment(sourceStmt);
  550.     
  551.     // early exit if a comment
  552.     if (isComment) {
  553.         longComment = getComment(sourceStmt);
  554.         return;
  555.     }
  556.  
  557.     keywords = getKeywordsFromHSpec(sourceStmt);
  558.     rhComment = getRhCommentFromText(sourceStmt);
  559.  
  560. }
  561. /**
  562.  * Extract keywords from raw h-spec
  563.  * @param sourceStmt hSpec String raw h-spec
  564.  * @return keywords String keywords
  565.  */
  566. private String getKeywordsFromHSpec(String sourceStmt) {
  567.     String keywords = "";
  568.  
  569.     log("start getKeywordsFromTextString " + sourceStmt);
  570.  
  571.     if (sourceStmt.length() > 7) {
  572.         int i = 80;
  573.         if (sourceStmt.length() <= i) {
  574.             i = sourceStmt.length();
  575.         }
  576.         keywords = sourceStmt.substring(7, i).toLowerCase().trim();
  577.  
  578.     }
  579.     return keywords;
  580. }
  581.  
  582. }
  583.  
  584.  
  585. /**
  586.  * This stores the various column based fields for a d-spec
  587.  * This object tokenises the line with the definitions.  It will also move backward 
  588.  * in the view's text lines to accumulate names continued from earlier lines.
  589.  * @param view LpexView 
  590.  * @param dSpec String a single raw d-spec (field / subfield)
  591.  * @author buck
  592.  *
  593.  */
  594. class DSpec {
  595.     public String spec = "";
  596.     public String name = "";
  597.     public String extType = "";
  598.     public String dsType = "";
  599.     public String defType = "";
  600.     public String fromPos = "";
  601.     public String len = "";
  602.     public String dataType = "";
  603.     public String decimals = "";
  604.     public String keywords = "";
  605.     public String rhComment = "";
  606.     public String dataTypeKwd = "";
  607.     public boolean isComment = false;
  608.     public String longComment = "";
  609.     
  610.     // constructor
  611.     public DSpec(LpexView view, String sourceStmt, int thisLine) {
  612.         
  613.         // I prefer lower case, so everything except the name will be monocased
  614.         // RDi trims each line, so they don't all equal 100 bytes...
  615.         // must test for out of bounds before substringing!
  616.         
  617.         /*
  618.          *  1 -  5 sequence number / text
  619.          *  6 -  6 dSpec 
  620.          *  7 - 21 name
  621.          * 22 - 22 external type (' ', 'e')
  622.          * 23 - 23 DS type (' ', 's', 'u')
  623.          * 24 - 25 def type (' ', 'c', 'ds', 'pi', 'pr')
  624.          * 26 - 32 from
  625.          * 33 - 39 len / to
  626.          * 40 - 40 type (a, p, i, z, *, etc)
  627.          * 41 - 42 decimal
  628.          * 44 - 80 keywords
  629.          * 81 -100 comment
  630.          * 
  631.          * Alternatively, there can be a comment of the form:
  632.          *  6 -  6 dSpec 
  633.          *  7 -  7 *
  634.          *  8 -100 comment
  635.          *  
  636.          * Alternatively, there can be a comment of the form:  
  637.          * 6 -  7 blanks
  638.          * 8 -100 // comment.  Note that there can be any number of blanks 
  639.          *                     preceding the //.
  640.          *                     
  641.          * Alternatively, there can be a continuation line of the form:
  642.          * 6 -  6 d
  643.          * 7 - 80 someName...                     
  644.          * 
  645.          */
  646.             
  647.         spec = getSpecFromText(sourceStmt);
  648.         
  649.         isComment = isComment(sourceStmt);
  650.         
  651.         // early exit if a comment
  652.         if (isComment) {
  653.             longComment = getComment(sourceStmt);
  654.             return;
  655.         }
  656.  
  657.         extType = getExtTypeFromText(sourceStmt);
  658.         dsType = getDsTypeFromText(sourceStmt);
  659.         defType = getDefTypeFromText(sourceStmt);
  660.         fromPos = getFromPosFromText(sourceStmt);
  661.         len = getLenFromText(sourceStmt);
  662.         dataType = getDataTypeFromText(sourceStmt);
  663.         decimals = getDecimalsFromText(sourceStmt);
  664.         keywords = getKeywordsFromDSpec(sourceStmt, len);
  665.         rhComment = getRhCommentFromText(sourceStmt);
  666.         // do this last to load the rest of the spec columns before it
  667.         name = getNameFromText(view, sourceStmt, thisLine);
  668.  
  669.     }
  670.  
  671.     // ==========================================================
  672.     // individual methods to extract the columns
  673.  
  674.     /**
  675.      * Extract name from raw d-spec
  676.      * @param view LpexView
  677.      * @param sourceStmt raw d-spec
  678.      * @param thisLine int line number passed in
  679.      * @return name String
  680.      */
  681.     private String getNameFromText(LpexView view, String sourceStmt, int thisLine ) {
  682.         // name is variable length, ending anywhere from 7 to 21
  683.         // so we could potentially have a name like i which would
  684.         // only be in column 7.
  685.         String name = "";
  686.         StringBuilder sbname = new StringBuilder();
  687.  
  688.         // line too short to hold a name
  689.         if (sourceStmt.length() < 6) {
  690.             return "";
  691.         }
  692.         
  693.         int i = 21;
  694.         if (sourceStmt.length() <= i) {
  695.             i = sourceStmt.length();
  696.         }    
  697.         sbname = sbname.append(sourceStmt.substring(6, i).trim());
  698.         
  699.         
  700.         // names can be continued on another line
  701.         // we started on the specification line;
  702.         // back up until we run out of continuation lines
  703.         // go backward from the line with the specs
  704.         for (int j = thisLine - 1; j != 0; j--) {
  705.             String sourceStmtPrior = view.elementText(j);
  706.             String specPrior = "";
  707.             String namePrior = "";
  708.             String defTypePrior = "";
  709.             String defTypePrior1 = "";
  710.             boolean isCommentPrior = false;
  711.             
  712.             specPrior = getSpecFromText(sourceStmtPrior);
  713.             isCommentPrior = isComment(sourceStmtPrior);
  714.  
  715.             // read another line if this is a comment
  716.             if (isCommentPrior) {
  717.                 continue;
  718.             }
  719.  
  720.             // line too short to hold a name
  721.             if (sourceStmtPrior.length() <= 6) {
  722.                 continue;
  723.             }
  724.             
  725.             i = 21;
  726.             if (sourceStmtPrior.length() <= i) {
  727.                 i = sourceStmtPrior.length();
  728.             }    
  729.             namePrior = sourceStmtPrior.substring(6, i).trim();
  730.                 
  731.             defTypePrior1 = defTypePrior;
  732.             defTypePrior = getDefTypeFromText(sourceStmtPrior);
  733.             
  734.             // is the name continued?
  735.             if (sourceStmtPrior.matches(".*\\.\\.\\.")) {
  736.                 sbname.insert(0, sourceStmtPrior.substring(6, sourceStmtPrior.length() - 3).trim());
  737.                 continue;
  738.             } else {
  739.                 // if d or p spec AND
  740.                 // name is blank AND
  741.                 // defType (s, pi etc) doesn't change THEN
  742.                 // it's legal and read another
  743.                 if ((specPrior.equals("d") || specPrior.equals("p")) &&
  744.                     (namePrior.length() == 0) &&
  745.                     (defTypePrior.equals(defTypePrior1))) {
  746.                     continue;
  747.                 }
  748.                 break;
  749.             }
  750.         }
  751.  
  752.         
  753.         // convert the StringBuilder name to the permanent String
  754.         name = sbname.toString();
  755.         return name;
  756.     }
  757.  
  758.     /**
  759.      * Get external data type from raw d-spec
  760.      * @param sourceStmt String raw d-spec
  761.      * @return extType String
  762.      */
  763.     private String getExtTypeFromText(String sourceStmt) {
  764.         String extType = "";
  765.         
  766.         if (sourceStmt.length() > 21) {
  767.             extType = sourceStmt.substring(21, 22).toLowerCase();
  768.         }
  769.         
  770.         return extType;
  771.     }
  772.  
  773.     /**
  774.      * Extract data structure type from d-spec
  775.      * @param sourceStmt String raw d-spec
  776.      * @return dsType String data structure type
  777.      */
  778.     private String  getDsTypeFromText(String sourceStmt) {
  779.         String dsType = "";
  780.         
  781.         if (sourceStmt.length() > 22) {
  782.             dsType = sourceStmt.substring(22, 23).toLowerCase();
  783.         }
  784.         return dsType;
  785.     }
  786.  
  787.     /**
  788.      * Extract definition type from raw d-spec
  789.      * @param sourceStmt dSpec String raw d-spec
  790.      * @return defType String definition type
  791.      */
  792.     private String getDefTypeFromText(String sourceStmt) {
  793.         String defType = "";
  794.         
  795.         if (sourceStmt.length() > 23) {
  796.             int i = 25;
  797.             if (sourceStmt.length() <= i) {
  798.                 i = sourceStmt.length();
  799.             }
  800.             defType = sourceStmt.substring(23, i).toLowerCase();
  801.         }
  802.         return defType;
  803.     }
  804.  
  805.     /**
  806.      * Extract From position from raw d-spec
  807.      * @param sourceStmt dSpec String raw d-spec
  808.      * @return fromPos String From position
  809.      */
  810.     private String getFromPosFromText(String sourceStmt) {
  811.         String fromPos = "";
  812.         
  813.         if (sourceStmt.length() > 31) {
  814.             fromPos = sourceStmt.substring(25, 32).toLowerCase().trim();
  815.         }
  816.         return fromPos;
  817.     }
  818.  
  819.     /**
  820.      * Extract Length / To position from raw d-spec
  821.      * @param sourceStmt dSpec String raw d-spec
  822.      * @return len String Length / To position 
  823.      */
  824.     private String getLenFromText(String sourceStmt) {
  825.         String len = "";
  826.         
  827.         if (sourceStmt.length() > 38) {
  828.             len = sourceStmt.substring(32, 39).toLowerCase().trim();
  829.         }
  830.         return len;
  831.     }
  832.  
  833.     /**
  834.      * Extract data type from raw d-spec
  835.      * @param sourceStmt dSpec String raw d-spec
  836.      * @return dataType String data type
  837.      */
  838.     private String getDataTypeFromText(String sourceStmt) {
  839.         String dataType = "";
  840.         
  841.         if (sourceStmt.length() > 39) {
  842.             dataType = sourceStmt.substring(39, 40).toLowerCase().trim();
  843.         }
  844.         return dataType;
  845.     }
  846.  
  847.     /**
  848.      * Extract decimals from raw d-spec
  849.      * @param sourceStmt dSpec String raw d-spec
  850.      * @return decimals String decimals
  851.      */
  852.     private String getDecimalsFromText(String sourceStmt) {
  853.         String decimals = "";
  854.         
  855.         if (sourceStmt.length() > 41) {
  856.             decimals = sourceStmt.substring(40, 42).toLowerCase().trim();
  857.         }
  858.         return decimals;
  859.     }
  860.  
  861.     /**
  862.     * Extract keywords from raw d-spec
  863.     * @param sourceStmt dSpec String raw d-spec
  864.     * @param len String to / length
  865.     * @return keywords String keywords
  866.     */
  867.     private String getKeywordsFromDSpec(String sourceStmt, String len) {
  868.     String keywords = "";
  869.     String keywordsAdj = "";
  870.  
  871.     log("start getKeywordsFromTextString " + sourceStmt);
  872.  
  873.     if (sourceStmt.length() > 43) {
  874.         int i = 80;
  875.         if (sourceStmt.length() <= i) {
  876.             i = sourceStmt.length();
  877.         }
  878.         keywords = sourceStmt.substring(43, i).toLowerCase().trim();
  879.         
  880.         // do we have a length adjustment?
  881.         if (keywords.length() > 0) {                        // have keywords
  882.             log("keywords.length()=" + keywords.length());    
  883.             if (len.matches(".*\\+.*")) {                    // have plus
  884.                 log("len.matches +");
  885.                 if (keywords.matches(".*like(.*).*")) {        // have LIKE()
  886.                     log("keywords.matches like(");
  887.                     
  888.                     // yes, length adjustment
  889.                     // delete the spaces
  890.                     String lenAdj = len.replace(" ", "").trim();
  891.                     log("lenAdj=" + lenAdj);
  892.  
  893.                     // split the LIKE() into two strings by use of regex groups
  894.                     // ...LIKE(LIKEVAR
  895.                     // ) INZ(12)...
  896.                     Pattern likeSplit = Pattern.compile("(.*like\\([^\\)]*)(\\).*)");
  897.                     Matcher m = likeSplit.matcher(keywords);
  898.                     if (m.matches()) {
  899.                         log("group 1=" + m.group(1));
  900.                         log("group 1=" + m.group(2));
  901.                     
  902.                         // re-assemble with the length adjustment inserted
  903.                         keywordsAdj = m.group(1) + ": " + lenAdj + m.group(2);
  904.                         log("keywordsAdj=" + keywordsAdj);
  905.                         
  906.                         keywords = keywordsAdj;
  907.                     } else {
  908.                         log("no match");
  909.                     }
  910.                 }
  911.             }
  912.             
  913.         }
  914.     }
  915.     return keywords;
  916.     }
  917.     
  918. }
  919.  
  920. }
  921.  
  922.  
© 2004-2019 by midrange.com generated in 0.209s valid xhtml & css