Analyzing Commands with Java

As I’ve mentioned in previous posts … building tools can be a fun & rewarding part of the job.

As part of a recent programming task, I had to do some analysis on commands to determine what parameters were supported in the SQL variant of the language compiler and what parameters were not supported.

I knew that the QCDRCMDD command could extract a commands definition to XML … and a little digging determined that the JT400 object Command could do it in Java.

A little bit of XML processing and I could get some good analysis very easily…

Here’s the code I put together … it’s quite specialized … but I think it could give you some ideas:

import java.io.*;
import java.util.*;

import javax.xml.parsers.*;

import org.w3c.dom.*;

import com.ibm.as400.access.*;

public class AnalyzeCommand {
     private static final DocumentBuilderFactory BUILDER_FACTORY = 
          DocumentBuilderFactory.newInstance();

     public static class CompareSet {

          public String sqlCmd;
          public String nonSqlCmd;

          public CompareSet(String sqlCmd, String nonSqlCmd) {
               this.sqlCmd = sqlCmd;
               this.nonSqlCmd = nonSqlCmd;
          }

          public String toString() {
               return sqlCmd + "/" + nonSqlCmd;
          }
     }

     private static final CompareSet[] CMD_SETS = new CompareSet[] {
          new CompareSet("CRTSQLRPG", "CRTRPGPGM"),
          new CompareSet("CRTSQLCBL", "CRTCBLPGM"),
          new CompareSet("CRTSQLPLI", "CRTPLIPGM"),
          new CompareSet("CRTSQLCI", "CRTBNDC"),
          new CompareSet("CRTSQLCI", "CRTCMOD"),
          new CompareSet("CRTSQLCPPI", "CRTBNDCPP"),
          new CompareSet("CRTSQLCPPI", "CRTCPPMOD"),
          new CompareSet("CRTSQLRPGI", "CRTRPGMOD"),
          new CompareSet("CRTSQLRPGI", "CRTBNDRPG"),
          new CompareSet("CRTSQLCBLI", "CRTCBLMOD"),
          new CompareSet("CRTSQLCBLI", "CRTBNDCBL"),
     };

     /**
     * @param args
     */
     public static void main(String[] args) {

          AnalyzeCommand rt = new AnalyzeCommand();
          rt.go();
     }

     private void go() {
          AS400 as400 = new AS400("ibmi.example.com", "userprofile", "password");

          CommandCall cc = new CommandCall(as400);
          try {
               cc.run("addlible qpli");
          } catch (Exception e) {
               e.printStackTrace();
          }

          for (CompareSet set : CMD_SETS) {

               Document nonSqlCmd = loadCommand(as400, set.nonSqlCmd);
               Document sqlCmd = loadCommand(as400, set.sqlCmd);

               List nonSqlKeywords = getParameterNames(nonSqlCmd);
               List sqlKeywords = getParameterNames(sqlCmd);

               System.out.println("Comparing " + set);
               for (String keyword : nonSqlKeywords) {
                    if (!sqlKeywords.contains(keyword)) {
                         System.out.println("t" + set.sqlCmd + " does not contain " + keyword);
                    }
               }

               System.out.println("");

//             for (String keyword : sqlKeywords) {
//
//                 if (!nonSqlKeywords.contains(keyword)) {
//                     System.out.println("t" + set.nonSqlCmd + " does not contain " +
//                            keyword);
//                 }
//             }
               System.out.println("----------");
          }
     }

     /**
     * Extract command parameter names from dom object.
     *
     * @param cmdDoc dom object containing parsed command
     * @return list of parameter names used on command
     */
     private List getParameterNames(Document cmdDoc) {

          List keywords = new ArrayList();

          Node rootNode = cmdDoc.getDocumentElement().getChildNodes().item(0);
          NodeList elementList = rootNode.getChildNodes();

          for (int i=0;i<elementList.getLength();i++) {
               Node element = elementList.item(i);

               String elementName = element.getNodeName();

               if (elementName.equalsIgnoreCase("parm")) {
                    NamedNodeMap attributes = element.getAttributes();

                    Node keywordNode = attributes.getNamedItem("Kwd");

                    String keywordName = keywordNode.getNodeValue();
                    keywords.add(keywordName);
               }
          }

          return keywords;
     }

     /**
     * Load the command, from the host, into a Dom object.
     *
     * @param as400 host
     * @param cmdName base command name
     * @return document object containing parsed command structure
     */
     private Document loadCommand(AS400 as400, String cmdName) {

          Document doc = null;
          String path = new QSYSObjectPathName("*LIBL", cmdName, "CMD").getPath();

          try {
               ObjectDescription od = new ObjectDescription(as400, path);
               od.refresh();

               path = od.getPath();

               Command cmd = new Command(as400, path);

               String xml = cmd.getXML();

               InputStream is = new ByteArrayInputStream(xml.getBytes());

               DocumentBuilder builder = BUILDER_FACTORY.newDocumentBuilder();

               doc = builder.parse(is);
          } catch (Exception e) {
               e.printStackTrace();
          }

          return doc;
     }

}

1 Reply to “Analyzing Commands with Java”

Leave a Reply to Buck Cancel reply

Your email address will not be published.