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 */
017package org.apache.commons.validator.util;
018
019import 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$
040 */
041public class Flags implements Serializable, Cloneable {
042
043    private static final long serialVersionUID = 8481587558770237995L;
044
045    /**
046     * Represents the current flag state.
047     */
048    private long flags = 0;
049
050    /**
051     * Create a new Flags object.
052     */
053    public Flags() {
054        super();
055    }
056
057    /**
058     * Initialize a new Flags object with the given flags.
059     *
060     * @param flags collection of boolean flags to represent.
061     */
062    public Flags(long flags) {
063        super();
064        this.flags = flags;
065    }
066
067    /**
068     * Returns the current flags.
069     *
070     * @return collection of boolean flags represented.
071     */
072    public long getFlags() {
073        return this.flags;
074    }
075
076    /**
077     * Tests whether the given flag is on.  If the flag is not a power of 2
078     * (ie. 3) this tests whether the combination of flags is on.
079     *
080     * @param flag Flag value to check.
081     *
082     * @return whether the specified flag value is on.
083     */
084    public boolean isOn(long flag) {
085        return (this.flags & flag) == flag;
086    }
087
088    /**
089     * Tests whether the given flag is off.  If the flag is not a power of 2
090     * (ie. 3) this tests whether the combination of flags is off.
091     *
092     * @param flag Flag value to check.
093     *
094     * @return whether the specified flag value is off.
095     */
096    public boolean isOff(long flag) {
097        return (this.flags & flag) == 0;
098    }
099
100    /**
101     * Turns on the given flag.  If the flag is not a power of 2 (ie. 3) this
102     * turns on multiple flags.
103     *
104     * @param flag Flag value to turn on.
105     */
106    public void turnOn(long flag) {
107        this.flags |= flag;
108    }
109
110    /**
111     * Turns off the given flag.  If the flag is not a power of 2 (ie. 3) this
112     * turns off multiple flags.
113     *
114     * @param flag Flag value to turn off.
115     */
116    public void turnOff(long flag) {
117        this.flags &= ~flag;
118    }
119
120    /**
121     * Turn off all flags.
122     */
123    public void turnOffAll() {
124        this.flags = 0;
125    }
126
127    /**
128     * Turn off all flags.  This is a synonym for <code>turnOffAll()</code>.
129     * @since Validator 1.1.1
130     */
131    public void clear() {
132        this.flags = 0;
133    }
134
135    /**
136     * Turn on all 64 flags.
137     */
138    public void turnOnAll() {
139        this.flags = 0xFFFFFFFFFFFFFFFFl;
140    }
141
142    /**
143     * Clone this Flags object.
144     *
145     * @return a copy of this object.
146     * @see java.lang.Object#clone()
147     */
148    @Override
149    public Object clone() {
150        try {
151            return super.clone();
152        } catch(CloneNotSupportedException e) {
153            throw new RuntimeException("Couldn't clone Flags object.");
154        }
155    }
156
157    /**
158     * Tests if two Flags objects are in the same state.
159     * @param obj object being tested
160     * @see java.lang.Object#equals(java.lang.Object)
161     *
162     * @return whether the objects are equal.
163     */
164    @Override
165    public boolean equals(Object obj) {
166        if (!(obj instanceof Flags)) {
167            return false;
168        }
169
170        if (obj == this) {
171            return true;
172        }
173
174        Flags f = (Flags) obj;
175
176        return this.flags == f.flags;
177    }
178
179    /**
180     * The hash code is based on the current state of the flags.
181     * @see java.lang.Object#hashCode()
182     *
183     * @return the hash code for this object.
184     */
185    @Override
186    public int hashCode() {
187        return (int) this.flags;
188    }
189
190    /**
191     * Returns a 64 length String with the first flag on the right and the
192     * 64th flag on the left.  A 1 indicates the flag is on, a 0 means it's
193     * off.
194     *
195     * @return string representation of this object.
196     */
197    @Override
198    public String toString() {
199        StringBuilder bin = new StringBuilder(Long.toBinaryString(this.flags));
200        for (int i = 64 - bin.length(); i > 0; i--) { // CHECKSTYLE IGNORE MagicNumber
201            bin.insert(0, "0");
202        }
203        return bin.toString();
204    }
205
206}