Home | History | Annotate | Download | only in options
      1 // =================================================================================================
      2 // ADOBE SYSTEMS INCORPORATED
      3 // Copyright 2006 Adobe Systems Incorporated
      4 // All Rights Reserved
      5 //
      6 // NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
      7 // of the Adobe license agreement accompanying it.
      8 // =================================================================================================
      9 
     10 package com.adobe.xmp.options;
     11 
     12 import java.util.HashMap;
     13 import java.util.Map;
     14 
     15 import com.adobe.xmp.XMPError;
     16 import com.adobe.xmp.XMPException;
     17 
     18 /**
     19  * The base class for a collection of 32 flag bits. Individual flags are defined as enum value bit
     20  * masks. Inheriting classes add convenience accessor methods.
     21  *
     22  * @since 24.01.2006
     23  */
     24 public abstract class Options
     25 {
     26 	/** the internal int containing all options */
     27 	private int options = 0;
     28 	/** a map containing the bit names */
     29 	private Map optionNames = null;
     30 
     31 
     32 	/**
     33 	 * The default constructor.
     34 	 */
     35 	public Options()
     36 	{
     37 		// EMTPY
     38 	}
     39 
     40 
     41 	/**
     42 	 * Constructor with the options bit mask.
     43 	 *
     44 	 * @param options the options bit mask
     45 	 * @throws XMPException If the options are not correct
     46 	 */
     47 	public Options(int options) throws XMPException
     48 	{
     49 		assertOptionsValid(options);
     50 		setOptions(options);
     51 	}
     52 
     53 
     54 	/**
     55 	 * Resets the options.
     56 	 */
     57 	public void clear()
     58 	{
     59 		options = 0;
     60 	}
     61 
     62 
     63 	/**
     64 	 * @param optionBits an option bitmask
     65 	 * @return Returns true, if this object is equal to the given options.
     66 	 */
     67 	public boolean isExactly(int optionBits)
     68 	{
     69 		return getOptions() == optionBits;
     70 	}
     71 
     72 
     73 	/**
     74 	 * @param optionBits an option bitmask
     75 	 * @return Returns true, if this object contains all given options.
     76 	 */
     77 	public boolean containsAllOptions(int optionBits)
     78 	{
     79 		return (getOptions() & optionBits) == optionBits;
     80 	}
     81 
     82 
     83 	/**
     84 	 * @param optionBits an option bitmask
     85 	 * @return Returns true, if this object contain at least one of the given options.
     86 	 */
     87 	public boolean containsOneOf(int optionBits)
     88 	{
     89 		return ((getOptions()) & optionBits) != 0;
     90 	}
     91 
     92 
     93 	/**
     94 	 * @param optionBit the binary bit or bits that are requested
     95 	 * @return Returns if <emp>all</emp> of the requested bits are set or not.
     96 	 */
     97 	protected boolean getOption(int optionBit)
     98 	{
     99 		return (options & optionBit) != 0;
    100 	}
    101 
    102 
    103 	/**
    104 	 * @param optionBits the binary bit or bits that shall be set to the given value
    105 	 * @param value the boolean value to set
    106 	 */
    107 	public void setOption(int optionBits, boolean value)
    108 	{
    109 		options = value ? options | optionBits : options & ~optionBits;
    110 	}
    111 
    112 
    113 	/**
    114 	 * Is friendly to access it during the tests.
    115 	 * @return Returns the options.
    116 	 */
    117 	public int getOptions()
    118 	{
    119 		return options;
    120 	}
    121 
    122 
    123 	/**
    124 	 * @param options The options to set.
    125 	 * @throws XMPException
    126 	 */
    127 	public void setOptions(int options) throws XMPException
    128 	{
    129 		assertOptionsValid(options);
    130 		this.options = options;
    131 	}
    132 
    133 
    134 	/**
    135 	 * @see Object#equals(Object)
    136 	 */
    137 	public boolean equals(Object obj)
    138 	{
    139 		return getOptions() == ((Options) obj).getOptions();
    140 	}
    141 
    142 
    143 	/**
    144 	 * @see java.lang.Object#hashCode()
    145 	 */
    146 	public int hashCode()
    147 	{
    148 		return getOptions();
    149 	}
    150 
    151 
    152 	/**
    153 	 * Creates a human readable string from the set options. <em>Note:</em> This method is quite
    154 	 * expensive and should only be used within tests or as
    155 	 * @return Returns a String listing all options that are set to <code>true</code> by their name,
    156 	 * like &quot;option1 | option4&quot;.
    157 	 */
    158 	public String getOptionsString()
    159 	{
    160 		if (options != 0)
    161 		{
    162 			StringBuffer sb = new StringBuffer();
    163 			int theBits = options;
    164 			while (theBits != 0)
    165 			{
    166 				int oneLessBit = theBits & (theBits - 1); // clear rightmost one bit
    167 				int singleBit = theBits ^ oneLessBit;
    168 				String bitName = getOptionName(singleBit);
    169 				sb.append(bitName);
    170 				if (oneLessBit != 0)
    171 				{
    172 					sb.append(" | ");
    173 				}
    174 				theBits = oneLessBit;
    175 			}
    176 			return sb.toString();
    177 		}
    178 		else
    179 		{
    180 			return "<none>";
    181 		}
    182 	}
    183 
    184 
    185 	/**
    186 	 * @return Returns the options as hex bitmask.
    187 	 */
    188 	public String toString()
    189 	{
    190 		return "0x" + Integer.toHexString(options);
    191 	}
    192 
    193 
    194 	/**
    195 	 * To be implemeted by inheritants.
    196 	 * @return Returns a bit mask where all valid option bits are set.
    197 	 */
    198 	protected abstract int getValidOptions();
    199 
    200 
    201 	/**
    202 	 * To be implemeted by inheritants.
    203 	 * @param option a single, valid option bit.
    204 	 * @return Returns a human readable name for an option bit.
    205 	 */
    206 	protected abstract String defineOptionName(int option);
    207 
    208 
    209 	/**
    210 	 * The inheriting option class can do additional checks on the options.
    211 	 * <em>Note:</em> For performance reasons this method is only called
    212 	 * when setting bitmasks directly.
    213 	 * When get- and set-methods are used, this method must be called manually,
    214 	 * normally only when the Options-object has been created from a client
    215 	 * (it has to be made public therefore).
    216 	 *
    217 	 * @param options the bitmask to check.
    218 	 * @throws XMPException Thrown if the options are not consistent.
    219 	 */
    220 	protected void assertConsistency(int options) throws XMPException
    221 	{
    222 		// empty, no checks
    223 	}
    224 
    225 
    226 	/**
    227 	 * Checks options before they are set.
    228 	 * First it is checked if only defined options are used,
    229 	 * second the additional {@link Options#assertConsistency(int)}-method is called.
    230 	 *
    231 	 * @param options the options to check
    232 	 * @throws XMPException Thrown if the options are invalid.
    233 	 */
    234 	private void assertOptionsValid(int options) throws XMPException
    235 	{
    236 		int invalidOptions = options & ~getValidOptions();
    237 		if (invalidOptions == 0)
    238 		{
    239 			assertConsistency(options);
    240 		}
    241 		else
    242 		{
    243 			throw new XMPException("The option bit(s) 0x" + Integer.toHexString(invalidOptions)
    244 					+ " are invalid!", XMPError.BADOPTIONS);
    245 		}
    246 	}
    247 
    248 
    249 
    250 	/**
    251 	 * Looks up or asks the inherited class for the name of an option bit.
    252 	 * Its save that there is only one valid option handed into the method.
    253 	 * @param option a single option bit
    254 	 * @return Returns the option name or undefined.
    255 	 */
    256 	private String getOptionName(int option)
    257 	{
    258 		Map optionsNames = procureOptionNames();
    259 
    260 		Integer key = new Integer(option);
    261 		String result = (String) optionsNames.get(key);
    262 		if (result == null)
    263 		{
    264 			result = defineOptionName(option);
    265 			if (result != null)
    266 			{
    267 				optionsNames.put(key, result);
    268 			}
    269 			else
    270 			{
    271 				result = "<option name not defined>";
    272 			}
    273 		}
    274 
    275 		return result;
    276 	}
    277 
    278 
    279 	/**
    280 	 * @return Returns the optionNames map and creates it if required.
    281 	 */
    282 	private Map procureOptionNames()
    283 	{
    284 		if (optionNames == null)
    285 		{
    286 			optionNames = new HashMap();
    287 		}
    288 		return optionNames;
    289 	}
    290 }
    291