001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.validator.util;
018    
019    import java.io.Serializable;
020    
021    /**
022     * Represents a collection of 64 boolean (on/off) flags.  Individual flags 
023     * are represented by powers of 2.  For example,<br/>
024     * Flag 1 = 1<br/>
025     * Flag 2 = 2<br/>
026     * Flag 3 = 4<br/>
027     * Flag 4 = 8<br/><br/>
028     * or using shift operator to make numbering easier:<br/>
029     * Flag 1 = 1 &lt;&lt; 0<br/>
030     * Flag 2 = 1 &lt;&lt; 1<br/>
031     * Flag 3 = 1 &lt;&lt; 2<br/>
032     * Flag 4 = 1 &lt;&lt; 3<br/>
033     * 
034     * <p>
035     * There cannot be a flag with a value of 3 because that represents Flag 1 
036     * and Flag 2 both being on/true.
037     * </p>
038     *
039     * @version $Revision: 493905 $ $Date: 2007-01-08 03:11:38 +0100 (Mo, 08. Jan 2007) $
040     */
041    public class Flags implements Serializable {
042    
043        /**
044         * Represents the current flag state.
045         */
046        private long flags = 0;
047    
048        /**
049         * Create a new Flags object.
050         */
051        public Flags() {
052            super();
053        }
054    
055        /**
056         * Initialize a new Flags object with the given flags.
057         *
058         * @param flags collection of boolean flags to represent.
059         */
060        public Flags(long flags) {
061            super();
062            this.flags = flags;
063        }
064    
065        /**
066         * Returns the current flags.
067         *
068         * @return collection of boolean flags represented.
069         */
070        public long getFlags() {
071            return this.flags;
072        }
073    
074        /**
075         * Tests whether the given flag is on.  If the flag is not a power of 2 
076         * (ie. 3) this tests whether the combination of flags is on.
077         *
078         * @param flag Flag value to check.
079         *
080         * @return whether the specified flag value is on.
081         */
082        public boolean isOn(long flag) {
083            return (this.flags & flag) > 0;
084        }
085    
086        /**
087         * Tests whether the given flag is off.  If the flag is not a power of 2 
088         * (ie. 3) this tests whether the combination of flags is off.
089         *
090         * @param flag Flag value to check.
091         *
092         * @return whether the specified flag value is off.
093         */
094        public boolean isOff(long flag) {
095            return (this.flags & flag) == 0;
096        }
097    
098        /**
099         * Turns on the given flag.  If the flag is not a power of 2 (ie. 3) this
100         * turns on multiple flags.
101         *
102         * @param flag Flag value to turn on.
103         */
104        public void turnOn(long flag) {
105            this.flags |= flag;
106        }
107    
108        /**
109         * Turns off the given flag.  If the flag is not a power of 2 (ie. 3) this
110         * turns off multiple flags.
111         *
112         * @param flag Flag value to turn off.
113         */
114        public void turnOff(long flag) {
115            this.flags &= ~flag;
116        }
117    
118        /**
119         * Turn off all flags.
120         */
121        public void turnOffAll() {
122            this.flags = 0;
123        }
124        
125        /**
126         * Turn off all flags.  This is a synonym for <code>turnOffAll()</code>.
127         * @since Validator 1.1.1
128         */
129        public void clear() {
130            this.flags = 0;
131        }
132    
133        /**
134         * Turn on all 64 flags.
135         */
136        public void turnOnAll() {
137            this.flags = Long.MAX_VALUE;
138        }
139    
140        /**
141         * Clone this Flags object.
142         *
143         * @return a copy of this object.
144         * @see java.lang.Object#clone()
145         */
146        public Object clone() {
147            try {
148                return super.clone();
149            } catch(CloneNotSupportedException e) {
150                throw new RuntimeException("Couldn't clone Flags object.");
151            }
152        }
153    
154        /**
155         * Tests if two Flags objects are in the same state.
156         * @param obj object being tested
157         * @see java.lang.Object#equals(java.lang.Object)
158         *
159         * @return whether the objects are equal.
160         */
161        public boolean equals(Object obj) {
162            if (!(obj instanceof Flags)) {
163                return false;
164            }
165    
166            if (obj == this) {
167                return true;
168            }
169    
170            Flags f = (Flags) obj;
171    
172            return this.flags == f.flags;
173        }
174    
175        /**
176         * The hash code is based on the current state of the flags.
177         * @see java.lang.Object#hashCode()
178         *
179         * @return the hash code for this object.
180         */
181        public int hashCode() {
182            return (int) this.flags;
183        }
184    
185        /**
186         * Returns a 64 length String with the first flag on the right and the 
187         * 64th flag on the left.  A 1 indicates the flag is on, a 0 means it's 
188         * off.
189         *
190         * @return string representation of this object.
191         */
192        public String toString() {
193            StringBuffer bin = new StringBuffer(Long.toBinaryString(this.flags));
194            for (int i = 64 - bin.length(); i > 0; i--) {
195                bin.insert(0, "0");
196            }
197            return bin.toString();
198        }
199    
200    }