
/*---------------------------------------------------------------------------
 * 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.
 *---------------------------------------------------------------------------
 */

package com.dalsemi.onewire.utils;

import java.io.File;
import java.util.Vector;
import java.util.Enumeration;
import com.dalsemi.onewire.OneWireException;
import com.dalsemi.onewire.utils.OWPathElement;
import com.dalsemi.onewire.container.OneWireContainer;
import com.dalsemi.onewire.container.SwitchContainer;
import com.dalsemi.onewire.adapter.DSPortAdapter;
import com.dalsemi.onewire.adapter.OneWireIOException;


/**
 * 1-Wire Network path.
 *
 * @version    0.00, 12 September 2000
 * @author     DS
 */
public class OWPath
{

   //--------
   //-------- Variables 
   //--------

   /** Elements of the path in a Vector */
   private Vector elements;

   /** Adapter where this path is based */
   private DSPortAdapter adapter;

   //--------
   //-------- Constructor
   //--------

   /**
    * Create a new empty path
    *
    * @param  adapter where the path is based
    */
   public OWPath (DSPortAdapter adapter)
   {
      this.adapter = adapter;
      elements     = new Vector(2, 1);
   }

   /**
    * Create a new path with a starting path
    *
    * @param  adapter where the path is based
    * @param  currentPath path to start this path on
    */
   public OWPath (DSPortAdapter adapter, OWPath currentOWPath)
   {
      this.adapter = adapter;
      elements     = new Vector(2, 1);

      copy(currentOWPath);
   }

   /**
    * Copy the provided path into this path
    *
    * @param  currentOWPath path to copy from
    */
   public void copy (OWPath currentOWPath)
   {
      elements.removeAllElements();

      if (currentOWPath != null)
      {

         // enumerature through elements in current path
         for (Enumeration path_enum = currentOWPath.getAllOWPathElements();
                 path_enum.hasMoreElements(); )
         {

            // cast the enum as a OWPathElements and add to vector
            elements.addElement(( OWPathElement ) path_enum.nextElement());
         }
      }
   }

   /**
    * Add a path element
    *
    * @param owc device that has multiple channels
    * @param channel of device that represents this path element
    */
   public void add (OneWireContainer owc, int channel)
   {
      elements.addElement(new OWPathElement(owc, channel));
   }

   /**
    * Compare this path with another path
    *
    * @param compareOWPath path to compare to
    *
    * @return true if the paths are the same
    */
   public boolean equals (OWPath compareOWPath)
   {
      return (this.toString().equals(compareOWPath.toString()));
   }

   /**
    * Get an enumeration of all of the path elements
    *
    * @return enumeration of all of the path elements
    */
   public Enumeration getAllOWPathElements ()
   {
      return elements.elements();
   }

   /**
    * Get a string representation of this path
    *
    * @return string equivalient to the path
    */
   public String toString ()
   {
      String           st = new String("");
      OWPathElement    element;
      OneWireContainer owc;

      // append 'drive'
      try
      {
         st = adapter.getAdapterName() + "_" + adapter.getPortName()
              + File.separator;
      }
      catch (OneWireException e)
      {
         st = adapter.getAdapterName() + File.separator;
      }

      for (int i = 0; i < elements.size(); i++)
      {
         element = ( OWPathElement ) elements.elementAt(i);
         owc     = element.getContainer();

         // append 'directory' name
         st += owc.getAddressAsString() + "_" + element.getChannel()
               + File.separator;
      }

      return st;
   }

   /**
    * Open the path so that a remote device can be accessed
    *
    * @throws OneWireIOException
    * @throws OneWireException
    */
   public void open ()
      throws OneWireException, OneWireIOException
   {
      OWPathElement   path_element;
      SwitchContainer sw;
      byte[]          sw_state;

      // enumerature through elements in path
      for (int i = 0; i < elements.size(); i++)
      {

         // cast the enum as a OWPathElement 
         path_element = ( OWPathElement ) elements.elementAt(i);

         // get the switch
         sw = ( SwitchContainer ) path_element.getContainer();

         // turn on the elements channel
         sw_state = sw.readDevice();

         sw.setLatchState(path_element.getChannel(), true, sw.hasSmartOn(),
                          sw_state);
         sw.writeDevice(sw_state);
      }

      // check if not depth in path, do a reset so a resetless search will work
      if (elements.size() == 0)
      {
         adapter.reset();
      }
   }

   /**
    * Close each element in the path in reverse order
    *
    * @throws OneWireIOException
    * @throws OneWireException
    */
   public void close ()
      throws OneWireException, OneWireIOException
   {
      OWPathElement   path_element;
      SwitchContainer sw;
      byte[]          sw_state;

      // enumerature through elements in path
      for (int i = elements.size() - 1; i >= 0; i--)
      {

         // cast the enum as a OWPathElement 
         path_element = ( OWPathElement ) elements.elementAt(i);

         // get the switch
         sw = ( SwitchContainer ) path_element.getContainer();

         // turn off the elements channel
         sw_state = sw.readDevice();

         sw.setLatchState(path_element.getChannel(), false, false, sw_state);
         sw.writeDevice(sw_state);
      }
   }
}
