
/*---------------------------------------------------------------------------
 * Copyright (C) 1999,2000 Dallas Semiconductor Corporation, All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the name of Dallas Semiconductor
 * shall not be used except as stated in the Dallas Semiconductor
 * Branding Policy.
 *---------------------------------------------------------------------------
 */

import java.io.*;
import java.util.*;


public class BuildOneWireProgram
{

   /** Field overlayFileName           */
   public static String overlayFileName = "TINI_101_Overlay_OneWireAPI.jar";

   /** Field dependencyFileName           */
   public static String dependencyFileName = "tini_dependencies.txt";

   /**
    * Method main
    *
    *
    * @param args
    *
    * @throws IOException
    *
    */
   public static void main (String[] args)
      throws IOException
   {
      if ((args == null) || (args.length == 0))
      {
         System.out.println(
            "Dallas Semiconductor TINI1.01 OneWire Program Building Tool (9-15-00 KLA)");
         System.out.println(
            "---------------------------------------------------------------------------\r\n");
         System.out.println(
            "This program is meant to be used to help build one wire applications for the");
         System.out.println(
            "TINI board, firmware release 1.01.  The OneWireAPI has changed since the 1.01");
         System.out.println(
            "release.  In order to build programs that access the OneWire using the new API,");
         System.out.println(
            "a temporary wrapping layer is being used until TINI release 1.02 implements the");
         System.out.println(
            "new API.  This program helps cut out some of the details of building with the");
         System.out.println("wrapper layer in place.\r\n\r\n");
         System.out.println("Usage: ");
         System.out.println(
            "   java BuildOneWireProgram [options] [classes] [containers]");
         System.out.println();
         System.out.println(
            "options: -o FILENAME -- Specify the output file name for the tini executable.");
         System.out.println(
            "         -d DATABASE -- Specify the full path+filename for the tini.db database.");
         System.out.println(
            "         -v OVERLAY  -- Path to the TINI overlay.  This should be the path to");
         System.out.println("                        a jar file called '"
                            + overlayFileName + "'.");
         System.out.println(
            "                        Defaults tothe current directory.  If the file is");
         System.out.println(
            "                        in the directory d:\\develop\\lib, then use");
         System.out.println(
            "                        'd:\\develop\\lib\\' for OVERLAY.");
         System.out.println(
            "         -p PATH     -- Path to your containers.  If your container ");
         System.out.println(
            "                        OneWireContainerXX lives in the directory ");
         System.out.println(
            "                        d:\\develop\\com\\dalsemi\\onewire\\container\\,");
         System.out.println(
            "                        then use 'd:\\develop\\' for PATH");
         System.out.println(
            "         -t DEP_PATH -- Path to the dependency text database file.  This");
         System.out.println(
            "                        file is called tini_dependencies.txt and should be");
         System.out.println(
            "                        located where you installed the onewire distribution");
         System.out.println(
            "                        under the lib directory.  If you installed in");
         System.out.println(
            "                        d:\\onewire, use 'd:\\onewire\\' for DEP_PATH");
         System.out.println(
            "classes: Names of the classes you would like to include in your");
         System.out.println(
            "         application.  These should we fully defined path names.");
         System.out.println(
            "containers: Two digit hex numbers corresponding to the OneWire containers");
         System.out.println("            to build into your application.");
         System.out.println();
         System.out.println(
            "For example, for a program that uses containers for the DS1920, DS1921, and");
         System.out.println("the DS1996, I might try running: ");
         System.out.println(
            "   java BuildOneWireProgram ReadTemp.class 10 21 0C -o test.tini -d d:\\tini1.01\\bin\\tini.db");
         System.out.println();
         System.out.println(
            "***********************************************************************");
         System.out.println(
            "* NOTE:1. FILENAME defaults to application.tini                       *");
         System.out.println(
            "*      2. DATABASE deafults to tini.db (the current directory)        *");
         System.out.println(
            "*      3. Container hex digits must be uppercase--'0C' and not '0c'   *");
         System.out.println(
            "*      4. THE CONTAINERS MUST BE LOCATED IN THE DIRECTORY             *");
         System.out.println(
            "*            PATH/com/dalsemi/onewire/container/                      *");
         System.out.println(
            "*      5.  THE CONTAINERS MUST ALREADY BE COMPILED!                   *");
         System.out.println(
            "*      6. PATH and DEP_PATH default to the current directory          *");
         System.out.println(
            "*      7. You should specify options in the command line before       *");
         System.out.println(
            "*         any classes or containers.                                  *");
         System.out.println(
            "***********************************************************************");

         return;
      }

      Vector classes    = new Vector();
      Vector containers = new Vector();
      String path       = "com/dalsemi/onewire/container/OneWireContainer";
      String prepath    = "";
      String overlay    = "";
      String dep_path   = "";

      //first let's see if TINIConvertor is in our classpath
      try
      {
         Class c = Class.forName("TINIConvertor");
      }
      catch (Exception e)
      {
         System.out.println("TINIConvertor is not in your classpath!");
         System.out.println("***************************************\r\n");
         System.out.println(
            "Make sure the file tini.jar is in your classpath.");
         System.out.println(
            "You can do this from the command line by calling");
         System.out.println(
            "    java -classpath d:\\tini\\bin\\tini.jar;%classpath% BuildOneWireProgram [OPTIONS]");
         System.out.println(
            "\r\nIt may also be useful to include '.' in your classpath:");
         System.out.println(
            "    java -classpath d:\\tini\\bin\\tini.jar;.;%classpath% ...");

         return;
      }

      //consider special buttons
      boolean jib         = false;
      boolean sha         = false;
      String  application = "application.tini";
      String  tinidb      = "tini.db";

      for (int i = 0; i < args.length; i++)
      {
         String classfile = args [i];

         if (classfile.endsWith(".class"))

         //it must be a classfile
         {
            try
            {
               File f = new File(classfile);

               if (!f.exists())
               {
                  System.out.println("The class " + classfile
                                     + " does not exist!");

                  return;
               }
            }
            catch (Exception e)
            {
               System.out.println("Could not find the file " + classfile
                                  + ".  Bailing...");

               return;
            }

            classes.addElement(classfile);
         }
         else if (classfile.equals("-o"))
         {

            //then the next string is the desired application name
            i++;

            application = args [i];
         }
         else if (classfile.equals("-d"))
         {

            //then the next string is the desired full name for the db file
            i++;

            tinidb = args [i];
         }
         else if (classfile.equals("-p"))
         {

            //then the next string is the desired path to the containers
            i++;

            prepath = args [i];
         }
         else if (classfile.equals("-v"))
         {

            //then the next string is the desired path to the TINI overlay
            i++;

            overlay = args [i];
         }
         else if (classfile.equals("-t"))
         {

            //then the next string is the desired path to the TINI dependency file
            i++;

            dep_path = args [i];

            initializeDependencyFile(dep_path + dependencyFileName);
         }
         else
         {
            try
            {
               File f = new File(prepath + path + classfile + ".class");

               if (!f.exists())
               {
                  System.out.println("The container " + classfile
                                     + " does not exist!");

                  return;
               }
            }
            catch (Exception e)
            {
               System.out.println("Could not find the container " + classfile
                                  + ".  Bailing...");

               return;
            }

            //now add the dependencies here...
            initializeDependencyFile(dep_path + dependencyFileName);

            String[] dep = getDependencies(classfile);

            for (int x = 0; x < dep.length; x++)
            {
               System.out.println("Dep " + x + " : " + dep [x]);

               String element = prepath + "com/dalsemi/onewire/container/"
                                + dep [x] + ".class";

               if (containers.indexOf(element) == -1)   //avoid duplicates
                  containers.addElement(element);
            }

            /*                          if (classfile.equals("18"))
                                        {
                                            sha = true;
                                            containers.addElement(prepath+"com/dalsemi/onewire/container/SHAiButton.class");
                                        }
                                        if (classfile.equals("16"))
                                        {
                                            jib = true;
                                            containers.addElement(prepath+"com/dalsemi/onewire/container/JibComm.class");
                                            containers.addElement(prepath+"com/dalsemi/onewire/container/JibComm$BlockDataFragmenter.class");
                                        }
                    */
            containers.addElement(prepath + path + classfile + ".class");
         }
      }

      overlayFileName = overlay + overlayFileName;

      //let's do some more file existance checks
      try
      {
         File f1 = new File(overlayFileName);

         if (!f1.exists())
         {
            System.out.println("Cannot find the TINI overlay JAR file at "
                               + overlayFileName + ".");
            System.out.println("The file does not exist.  Bailing...");

            return;
         }

         f1 = new File(tinidb);

         if (!f1.exists())
         {
            System.out.println("Cannot find the TINI database file at "
                               + tinidb + ".");
            System.out.println("The file does not exist.  Bailing...");

            return;
         }
      }
      catch (Exception e)
      {
         System.out.println("General exception on file checks: "
                            + e.toString());
         System.out.println("Bailing...");
      }

      String[] s_classes = new String [classes.size()];

      for (int i = 0; i < s_classes.length; i++)
      {
         s_classes [i] = ( String ) classes.elementAt(i);
      }

      String[] s_containers = new String [containers.size()];

      for (int i = 0; i < s_containers.length; i++)
      {
         s_containers [i] = ( String ) containers.elementAt(i);
      }

      //now build the calling array
      String[] arguments =
         new String [2 + (s_classes.length * 2) + (s_containers.length * 2) + +2 + 2];
      int      j         = 0;

      for (int i = 0; i < s_classes.length; i++)
      {
         arguments [j++] = "-f";
         arguments [j++] = s_classes [i];
      }

      for (int i = 0; i < s_containers.length; i++)
      {
         arguments [j++] = "-f";
         arguments [j++] = s_containers [i];
      }
      arguments [j++]    = "-f";
      arguments [j++]    = overlayFileName;
      arguments [j++]    = "-o";
      arguments [j++]    = application;
      arguments [j++]    = "-d";
      arguments [j++]    = tinidb;

      //PrintStream out = System.out;
      try
      {

         //PrintStream os = new PrintStream(new ByteArrayOutputStream());
         //System.setOut(os);
         TINIConvertor.main(arguments);

         //System.setOut(out);
         System.out.println("\r\n\r\nConversion successful");
      }
      catch (Exception e)
      {

         //System.setOut(out);
         System.out.println("\r\n\r\nCould not create the application: "
                            + e.toString());
      }
   }

   private static Hashtable dependency   = null;
   private static String    dep_filename = null;

   private static void initializeDependencyFile (String filename)
   {
      if (dep_filename == null)
         dep_filename = new String(filename);
      else
      {
         if (dep_filename.equals(filename))
            return;   //we've already initialized on this file
         else         //we have not yet initialized on this file
            dep_filename = new String(filename);
      }

      Hashtable temp = new Hashtable();

      try
      {
         FileInputStream fin  = new FileInputStream(dep_filename);
         BufferedReader  in   =
            new BufferedReader(new InputStreamReader(fin));
         String          line = in.readLine();

         while (line != null)
         {
            if (line.length() > 1)
            {

               //line should be 2 characters of hex, then a space, then all the dependencies
               String hex = line.substring(0, 2);

               if (line.length() > 2)
                  line = line.substring(3);
               else
                  line = "";

               //                    System.out.println("Hash "+hex+", storing "+line);
               temp.put(hex, line);
            }

            line = in.readLine();
         }
      }
      catch (Exception e)
      {
         System.out.println("Failed to find dependencies: " + e.toString());

         return;
      }

      dependency = temp;
   }

   private static String[] getDependencies (String hex)
   {
      if (dependency == null)
         return new String [0];

      //hex should be a 2 digit hex string
      String          line = ( String ) dependency.get(hex);
      StringTokenizer st   = new StringTokenizer(line);
      int             len  = st.countTokens();
      String[]        temp = new String [len];
      int             i    = 0;

      while (st.hasMoreTokens())
      {
         temp [i++] = st.nextToken();
      }

      return temp;
   }
}
