Logo Search packages:      
Sourcecode: airport-utils version File versions  Download package

AirportInfoRecord.java

/*
 * AirportBaseStationConfigurator
 *
 * Copyright (C) 2000, Jonathan Sevy <jsevy@mcs.drexel.edu>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


package airport;


import java.math.*;
import java.util.*;
import byteblock.*;




/**
*     This class defines a structure to hold information about the location and format (type)
*     of a piece of information in the Airport memory block. Location is specified by a triple:
*     the object identifier number (1 to 68), row in the block (0 to 15), and column (0 to 15), 
*     where the ByteBlockWindow begins; size of the window is specified by giving the number of
*     rows and columns in the window; and the datatype is specified as one of the class's constants.
*     
*     The class also implements a toString() method which provides a pretty-printed representation
*     of the value in the window based on its datatype, and a setBytesFromString() method which
*     writes a value to the window given an appropriately formatted String representation.
*/

public class AirportInfoRecord
{
      public static final int CHAR_STRING = 0;
      public static final int IP_ADDRESS = 1;
      public static final int BYTE_STRING = 2;
      public static final int PHONE_NUMBER = 3;
      public static final int UNSIGNED_INTEGER = 4;
      public static final int BYTE = 5;
      public static final int LITTLE_ENDIAN_UNSIGNED_INTEGER = 6;
      
      
      public int dataType;
      public ByteBlockWindow byteBlockWindow;
      
      
      
      /**
      *     Create a new record with the specified parameters, creating a new ByteBlockRectangularWindow
      *     into the supplied ByteBlock.
      */
      
00066       public AirportInfoRecord(int baseStartIndex, int numRows, int numCols, int dataType, ByteBlock baseBlock)
      {
            this.dataType = dataType;
            this.byteBlockWindow = new ByteBlockRectangularWindow(baseStartIndex, numRows, numCols, baseBlock);
      }
      
      
      
      
      /**
      *     Create a new record of given datatype for the specified ByteBlockWindow.
      */
      
00079       public AirportInfoRecord(int dataType, ByteBlockWindow window)
      {
            this.dataType = dataType;
            this.byteBlockWindow = window;
      }
      
      
      
      
      /**
      *     Clear all bytes in the underlying ByteBlockWindow.
      */
      
00092       public void clearWindow()
      {
            byteBlockWindow.clearBytes();
      }
      
      
      
      
      /**
      *     Method which provides a pretty-printed representation of the value in the ByteBlockWindow 
      *     based on its datatype.
      */
      
00105       public String toString()
      {
            
            String returnString = new String();
            
            switch (dataType)
            {
                  case UNSIGNED_INTEGER:
                  {
                        try
                        {
                              byte[] bytes = byteBlockWindow.getBytes();
                              returnString = convertToUnsignedInteger(bytes);
                        }
                        catch (NumberFormatException e)
                        {
                              returnString = byteBlockWindow.toHexString();
                        }
                        
                        break;
                  }
                  
                  
                  case LITTLE_ENDIAN_UNSIGNED_INTEGER:
                  {
                        try
                        {
                              byte[] bytes = byteBlockWindow.getBytes();
                              bytes = reverseBytes(bytes);
                              
                              returnString = convertToUnsignedInteger(bytes);
                               
                        }
                        catch (NumberFormatException e)
                        {
                              returnString = byteBlockWindow.toHexString();
                        }
                        
                        break;
                  }
                  
                  
                  case CHAR_STRING:
                  {
                        
                        returnString = new String(byteBlockWindow.getBytes());
                        
                        // strip off trailing nulls, if any
                        int endIndex = returnString.indexOf(0x00);
                        if (endIndex >= 0)
                              returnString = returnString.substring(0, endIndex);
                        break;
                  }
                  
                  case PHONE_NUMBER:
                  {
                        returnString = convertToPhoneNumber(byteBlockWindow.getBytes());
                        break;
                  }
                  
                  
                  case IP_ADDRESS:
                  {
                        returnString = convertToIPAddress(byteBlockWindow.getBytes());
                        break;
                  }
      
                  
                  case BYTE:
                  case BYTE_STRING:
                  default:
                  {
                        returnString = byteBlockWindow.toHexString();
                        break;
                  }
            }
            
            return returnString;
      }
      
      
      
      
      private String convertToUnsignedInteger(byte[] bytes)
      {
            BigInteger bigInt = new BigInteger(1, bytes);
            return bigInt.toString();
      }
      
      
      
      private String convertToIPAddress(byte[] bytes)
      {
            String returnString = new String();
            int value;
            
            for (int i = 0; i < bytes.length - 1; i++)
            {
                  value = bytes[i];
                  if (value < 0)
                        value += 256;
                  returnString += value + ".";
                  
            }
            
            value = bytes[bytes.length - 1];
            if (value < 0)
                  value += 256;
            returnString += value;
            
            return returnString;
      }
      
      
      
      /**
      *     Utility method that does single-digit mapping from nibble (half-byte, 4-bit) values
      *     to appropriate char values. This is used in displaying phone numbers. The mapping is:
      *           0xA == '*'
      *           0xB == '#'
      *           0xC == ','
      *           0xD == ' '  (note: also used for both (!) left and right parens...
      *           0xE == '-'
      *           0xF == '.'
      */
      
00231       public static char decodePhoneDigit(byte digit)
      {
            
            char returnChar;
            
            if (digit == 0xA)       // represents star
                  returnChar = '*';       
            else if (digit == 0xB)  // represents pound
                  returnChar = '#';       
            else if (digit == 0xC)  // represents comma
                  returnChar = ',';
            else if (digit == 0xD)  // represents space (or parens...)
                  returnChar = ' ';
            else if (digit == 0xE)  // represents dash
                  returnChar = '-';
            else if (digit == 0xF)  // represents period
                  returnChar = '.';       
            else
                  returnChar = Byte.toString(digit).charAt(0);
                  
            return returnChar;
      }
      
      
      
      
      private String convertToPhoneNumber(byte[] bytes)
      {
            String returnString = new String();
            
            for (int i = 0; i < bytes.length; i++)
            {
                  
                  int left = (bytes[i] & 0xF0) >>> 4;
                  int right = bytes[i] & 0x0F;
                  
                  if (left == 0xE)  // represents dash
                        returnString += "-";
                  else if (left == 0xD)   // represents space
                        returnString += " ";
                  else if (left == 0xC)   // represents comma
                        returnString += ",";
                  else
                        returnString += left;
                  
                  if (right == 0xE) // represents dash
                        returnString += "-";
                  else if (right == 0xD)  // represents space
                        returnString += " ";
                  else if (right == 0xC)  // represents comma
                        returnString += ",";
                  else
                        returnString += right;
                        
            }
            
            return returnString;
      }
      
      
      
      
      /**
      *     Writes a value to the window given an appropriately formatted String representation for
      *     the value.
      */
      
00298       public void setBytesFromString(String valueString)
            throws ValueFormatException
      {
            
            byte[] bytes;
            int blockSize = byteBlockWindow.getSize();
                  
            switch (dataType)
            {
                  
                  case UNSIGNED_INTEGER:
                  {
                        bytes = convertFromUnsignedInteger(valueString);
                        break;
                  }
                  
                  case LITTLE_ENDIAN_UNSIGNED_INTEGER:
                  {
                        bytes = convertFromUnsignedInteger(valueString);
                        bytes = reverseBytes(bytes);
                        
                        break;
                  }
                  
                  case CHAR_STRING:
                  {
                        // add trailing null
                        valueString += "\u0000";
                        
                        if (valueString.length() > blockSize)
                        {
                              // System.out.println("Value format exception at " + OIDNum + " " + OIDRow + " " + OIDCol);
                              throw new ValueFormatException("Maximum " + (blockSize - 1) + " characters.");
                        }
                        else
                              bytes = valueString.getBytes();
                              
                        break;
                  }
                  
                  case PHONE_NUMBER:
                  {
                        bytes = convertFromPhoneNumber(valueString);
                        break;
                  }
                  
                  
                  case IP_ADDRESS:
                  {
                        bytes = convertFromIPv4Address(valueString);
                        break;
                  }
      
                  
                  case BYTE:
                  case BYTE_STRING:
                  default:
                  {
                        bytes = convertFromHexString(valueString);      
                        break;
                  }
            }
            
            // byteBlockWindow.writeBytes(startIndex, bytes);
            byteBlockWindow.writeBytes(bytes);
                        
      }
      
      
      
      
      private byte[] convertFromIPv4Address(String addressString)
            throws ValueFormatException
      {
            // might be partial address
            int length = byteBlockWindow.getSize();
            byte[] bytes = new byte[length];
            
            int i = 0;
            int value;
            StringTokenizer st = new StringTokenizer(addressString, ".");
            if (st.countTokens() != length)
            {
                  if (length == 4)
                        throw new ValueFormatException("Bad IP address: must be of form a.b.c.d, with a,b,c and d between 0 and 255.");
                  else
                        throw new ValueFormatException("Bad dotted address supplied: should have " + length + " components.");
            }
            
            while (st.hasMoreTokens())
            {
                  try
                  {
                        String component = st.nextToken();
                        value = Integer.parseInt(component);
                        if ((value < 0) || (value > 255))
                              throw new ValueFormatException("Bad IP address: must be of form a.b.c.d, with a,b,c and d between 0 and 255.");
                        else
                        {
                              bytes[i] = (byte)value;
                              i++;
                        }
                  }
                  catch (NumberFormatException e)
                  {
                        throw new ValueFormatException("Bad IP address: must be of form a.b.c.d, with a,b,c and d between 0 and 255.");
                  }
                  
            }
            
            return bytes;
      }
      
      
      
      
      
      /**
      *     Utility method that does single-digit mapping from char values to appropriate
      *     nibble (half-byte, 4-bit) values. This is used in encoding phone numbers. 
      *     The mapping is:
      *           0xA == '*'
      *           0xB == '#'
      *           0xC == ','
      *           0xD == ' '  (note: also used for both (!) left and right parens...
      *           0xE == '-'
      *           0xF == '.'
      */
      
00427       public static byte encodePhoneDigit(char digit)
            throws NumberFormatException
      {
            
            byte nibble;
            
            if (digit == '*')
                  nibble = 0xA;           // represents star
            else if (digit == '#')
                  nibble = 0xB;           // represents pound
            else if (digit == ',')
                  nibble = 0xC;           // represents comma
            else if ((digit == ' ') || (digit == '(') || (digit == ')'))      
                  nibble = 0xD;           // space or paren
            else if (digit == '-')  
                  nibble = 0xE;           // represents dash
            else if (digit == '.')
                  nibble = 0xF;           // represents period
            else
                  nibble = (byte)Character.digit(digit, 10);
            
            return nibble;
      }
      
      
      
      
      private byte[] convertFromPhoneNumber(String phoneNumber)
            throws ValueFormatException
      // Phone numbers are BCD encoded, with E for dash and D for space or paren
      {
            char[] chars = phoneNumber.toCharArray();
            byte[] bytes = new byte[(chars.length + 1)/2];
            
            for (int i = 0; i < chars.length; i++)
            {
                  byte nibble;
                  
                  if (chars[i] == '-')    // represents dash
                        nibble = 0xE;
                  else if ((chars[i] == ' ') || (chars[i] == '(') || (chars[i] == ')'))   
                        nibble = 0xD;           // space or paren
                  else if (chars[i] == ',')
                        nibble = 0xC;           // represents comma
                  else
                  {
                        try
                        {
                              nibble = (byte)Integer.parseInt(phoneNumber.substring(i,i+1));
                        }
                        catch(NumberFormatException e)
                        {
                              throw new ValueFormatException("Invalid phone number");
                        }
                  }
                  
                        
                  if (2 * (i/2) == i)           // i even, shift left
                        nibble = (byte)(nibble << 4);
                  
                  bytes[(i+1)/2] &= nibble;
                  
            }
            
            
            return bytes;
      }
      
      
      
      private byte[] convertFromUnsignedInteger(String valueString)
            throws ValueFormatException
      {
            int length = byteBlockWindow.getSize();
            byte[] bytes = new byte[length];
            
            try
            {
                  int minValue = 0;
                  long maxValue = 1;
                  for (int i = 0; i < length; i++)
                  {
                        maxValue *= 256;
                  }
                  maxValue -= 1;
                  
                  long value = Long.parseLong(valueString);
                  
                  if ((value < minValue) || (value > maxValue))
                         throw new ValueFormatException("Value must be between " + minValue + " and " + maxValue + ".");
                  
                  for (int i = 0; i < length; i++)
                  {
                        bytes[length - i - 1] = (byte)(value%256);
                        value = value/256;
                  }
            }
            catch (NumberFormatException e)
            {
                  throw new ValueFormatException("Bad number format.");
            }

            return bytes;
      }
      
      
      
      
      
      private byte[] convertFromHexString(String hexString)
            throws ValueFormatException
      {
            int length = byteBlockWindow.getSize();
            byte[] bytes = new byte[length];
            
            // eliminate spaces in string
            hexString.trim();
            int index;
            while((index = hexString.indexOf(' ')) != -1)
            {
                  hexString = hexString.substring(0,index) + hexString.substring(index+1);
            }
            
            // make sure have even number of hex digits
            if (2 * (hexString.length()/2) != hexString.length())
                  throw new ValueFormatException("Must have an even number of hexadecimal digits.");
            
            // make sure don't have too many bytes
            if (hexString.length() / 2 > length)
                  throw new ValueFormatException("Too many hexadecimal digits (maximum " + length + " bytes = " + 2*length + " hex digits).");
            
            for (int i = 0; i < (hexString.length()/2); i++)
            {
                  // get next pair of digits
                  String digitString = hexString.substring(2*i,2*i+2);
                  
                  try
                  {
                        int value = Integer.parseInt(digitString, 16);  
                        bytes[i] = (byte)value;
                  }
                  catch (NumberFormatException e)
                  {
                        throw new ValueFormatException("Entries must be hexadecimal digits (0 through 9 and a through f or A through F) or spaces.");
                  }
                  
            }
            
            return bytes;
      }
      
      
      
      
      private byte[] reverseBytes(byte[] inBytes)
      {
            int length = inBytes.length;
            byte[] outBytes = new byte[length];
            
            for (int i = 0; i < length; i++)
            {
                  outBytes[i] = inBytes[length - i - 1];
            }
            
            return outBytes;
      }

      
      

}

Generated by  Doxygen 1.6.0   Back to index