BitSelector.java

/*
** Module   :BitSelector.java
** Abstract :BitSelector, a subclass of BitField (one bit set to 1 at a time)
**
** Copyright (c) 2005-2017, Golden Code Development Corporation.
**
** -#- -I- --Date-- -T- --JPRM-- ----------------Description-----------------
** 001 SIY 20050216 ADD  @20016  Created initial implementation
** 002 SIY 20050310 CHG  @20355  Organized imports and reordered methods.                       
** 003 SIY 20050323 CHG  @20469  Fixed formatting.  
** 004 SIY 20050328 CHG  @20575  Fixed comments and other minor cleanups.
** 005 SIY 20050428 CHG  @21008  Fixed comments and formatting.
** 006 SIY 20050515 CHG  @21188  Extended comments.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.directory;

import java.util.BitSet;

/**
 * BitSelector, a subclass of BitField which allows only one bit set to 1 at a
 * time.
 * <p>
 * The main purpose of this class is to provide Java representation of the
 * <code>Bit Selector</code> attribute type.
 * 
 * @author  SIY
 * @version 1.0
 */
public class BitSelector
extends BitField
{
   /**
    * Construct an instance of specified width and with specified bit set to
    * <code>true</code>.
    * 
    * @param   width
    *          BitSelector width.
    * @param   index
    *          Set bit index.
    */
   public BitSelector(int width, int index)
   {
      super(width);
      set(index);
   }

   /**
    * Parse <code>String</code> like 00000100 and create an instance of
    * <code>BitSelector</code>.
    * 
    * @param   str
    *          Source string.
    * @return  New <code>BitSelector</code> instance or <code>null</code>
    *          if source string does not contain properly formatted bit field.
    */
   public static BitField valueOf(String str)
   {
      if (str == null || str.length() == 0)
         return null;

      BitField field = BitField.valueOf(str);

      if (field == null)
         return null;

      if (field.cardinality() != 1)
         return null;

      BitSelector res = new BitSelector(field.size(), field.nextSetBit(0));

      return res;
   }

   /**
    * This method is not allowed for use.
    * 
    * @param   set
    *          Ignored parameter.
    * @throws  IllegalArgumentException
    *          thrown for any try to call this method.
    */
   public void and(BitSet set)
   {
      disabled();
      super.and(set);
   }

   /**
    * This method is not allowed for use.
    * 
    * @param   set
    *          Ignored parameter.
    * @throws  IllegalArgumentException
    *          thrown for any try to call this method.
    */
   public void andNot(BitSet set)
   {
      disabled();
      super.andNot(set);
   }

   /**
    * This method is not allowed for use.
    * 
    * @throws  IllegalArgumentException
    *          thrown for any try to call this method.
    */
   public void clear()
   {
      disabled();
      super.clear();
   }

   /**
    * This method is not allowed for use.
    * 
    * @param   index
    *          Ignored parameter.
    * @throws  IllegalArgumentException
    *          thrown for any try to call this method.
    */
   public void clear(int index)
   {
      disabled();
      super.clear(index);
   }

   /**
    * This method is not allowed for use.
    * 
    * @param   from
    *          Ignored parameter.
    * @param   to
    *          Ignored parameter.
    * @throws  IllegalArgumentException
    *          thrown for any try to call this method.
    */
   public void clear(int from, int to)
   {
      disabled();
      super.clear(from, to);
   }

   /**
    * This method is not allowed for use.
    * 
    * @param   index
    *          Ignored parameter.
    * @throws  IllegalArgumentException
    *          thrown for any try to call this method.
    */
   public void flip(int index)
   {
      disabled();
      super.flip(index);
   }

   /**
    * This method is not allowed for use.
    * 
    * @param   from
    *          Ignored parameter.
    * @param   to
    *          Ignored parameter.
    * @throws  IllegalArgumentException
    *          thrown for any try to call this method.
    */
   public void flip(int from, int to)
   {
      disabled();
      super.flip(from, to);
   }

   /**
    * Set specified bit into <code>true</code>.
    * 
    * @param   index
    *          The index of the bit to set.
    * @throws  IndexOutOfBoundsException
    *          if the specified index is negative or exceeds BitSelector
    *          width.
    */
   public void set(int index)
   {
      int pos = nextSetBit(0);

      if (pos == -1) //First time bit is set
      {
         super.set(index);
         return;
      }

      if (pos == index) //Already set
         return;

      super.set(index); //If exception is thrown then state is preserved
      super.clear(pos); //Finally clear bit
   }

   /**
    * Set specified bit into specified value.
    * 
    * @param   index
    *          The index of the bit to set
    * @param   val
    *          New bit value.
    * @throws  IndexOutOfBoundsException
    *          if the specified index is negative or exceeds BitSelector
    *          width.
    */
   public void set(int index, boolean val)
   {
      if (!val)
         throw new IllegalArgumentException("Only true is allowed.");

      set(index);
   }

   /**
    * Set specified range of bits into <code>true</code>.
    * 
    * @param   from
    *          The index of the first bit in range.
    * @param   to
    *          The index of the last bit in range.
    * @throws  IndexOutOfBoundsException
    *          if the specified range does not fit into BitSelector width.
    */
   public void set(int from, int to)
   {
      if (to > (from + 1))
         throw new IllegalArgumentException("Range is too wide.");

      set(from);
   }

   /**
    * Set specified range of bits into specified value. The range width must
    * be 1 and value must be <code>true</code>.
    * 
    * @param   from
    *          The index of the first bit in range.
    * @param   to
    *          The index of the last bit in range.
    * @param   val
    *          New value for the range.
    * @throws  IndexOutOfBoundsException
    *          if the specified range does not fit into BitSelector width.
    */
   public void set(int from, int to, boolean val)
   {
      if (!val)
         throw new IllegalArgumentException("Only true is allowed.");

      set(from, to);
   }

   /**
    * Performs a logical XOR of this bit field with the argument bit set.
    * 
    * @param   set
    *          A bit set to perform operation with.
    * @throws  IndexOutOfBoundsException
    *          if the specified set is too wide.
    */
   public void xor(BitSet set)
   {
      if (set.cardinality() != 1 || set.nextSetBit(0) == nextSetBit(0))
         throw new IllegalArgumentException(
             "Too many bits set or bit positions the same in both selectors");

      super.xor(set);
   }

   /**
    * Just throw an exception
    * 
    * @throws  IllegalArgumentException
    *          if method is called.
    */
   private void disabled()
   {
      throw new IllegalArgumentException(
                                      "No calls to this method are allowed.");
   }
}