001/**
002 *
003 * Copyright 2003-2007 Jive Software.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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.jivesoftware.smackx.workgroup.util;
018
019import java.util.*;
020
021/**
022 * Utility methods frequently used by data classes and design-time
023 * classes.
024 */
025public final class ModelUtil {
026    private ModelUtil() {
027        //  Prevents instantiation.
028    }
029
030    /**
031     * This is a utility method that compares two objects when one or
032     * both of the objects might be <CODE>null</CODE>  The result of
033     * this method is determined as follows:
034     * <OL>
035     * <LI>If <CODE>o1</CODE> and <CODE>o2</CODE> are the same object
036     * according to the <CODE>==</CODE> operator, return
037     * <CODE>true</CODE>.
038     * <LI>Otherwise, if either <CODE>o1</CODE> or <CODE>o2</CODE> is
039     * <CODE>null</CODE>, return <CODE>false</CODE>.
040     * <LI>Otherwise, return <CODE>o1.equals(o2)</CODE>.
041     * </OL>
042     * <p/>
043     * This method produces the exact logically inverted result as the
044     * {@link #areDifferent(Object, Object)} method.<P>
045     * <p/>
046     * For array types, one of the <CODE>equals</CODE> methods in
047     * {@link java.util.Arrays} should be used instead of this method.
048     * Note that arrays with more than one dimension will require some
049     * custom code in order to implement <CODE>equals</CODE> properly.
050     */
051    public static final boolean areEqual(Object o1, Object o2) {
052        if (o1 == o2) {
053            return true;
054        }
055        else if (o1 == null || o2 == null) {
056            return false;
057        }
058        else {
059            return o1.equals(o2);
060        }
061    }
062
063    /**
064     * This is a utility method that compares two Booleans when one or
065     * both of the objects might be <CODE>null</CODE>  The result of
066     * this method is determined as follows:
067     * <OL>
068     * <LI>If <CODE>b1</CODE> and <CODE>b2</CODE> are both TRUE or
069     * neither <CODE>b1</CODE> nor <CODE>b2</CODE> is TRUE,
070     * return <CODE>true</CODE>.
071     * <LI>Otherwise, return <CODE>false</CODE>.
072     * </OL>
073     * <p/>
074     */
075    public static final boolean areBooleansEqual(Boolean b1, Boolean b2) {
076        // !jwetherb treat NULL the same as Boolean.FALSE
077        return (b1 == Boolean.TRUE && b2 == Boolean.TRUE) ||
078                (b1 != Boolean.TRUE && b2 != Boolean.TRUE);
079    }
080
081    /**
082     * This is a utility method that compares two objects when one or
083     * both of the objects might be <CODE>null</CODE>.  The result
084     * returned by this method is determined as follows:
085     * <OL>
086     * <LI>If <CODE>o1</CODE> and <CODE>o2</CODE> are the same object
087     * according to the <CODE>==</CODE> operator, return
088     * <CODE>false</CODE>.
089     * <LI>Otherwise, if either <CODE>o1</CODE> or <CODE>o2</CODE> is
090     * <CODE>null</CODE>, return <CODE>true</CODE>.
091     * <LI>Otherwise, return <CODE>!o1.equals(o2)</CODE>.
092     * </OL>
093     * <p/>
094     * This method produces the exact logically inverted result as the
095     * {@link #areEqual(Object, Object)} method.<P>
096     * <p/>
097     * For array types, one of the <CODE>equals</CODE> methods in
098     * {@link java.util.Arrays} should be used instead of this method.
099     * Note that arrays with more than one dimension will require some
100     * custom code in order to implement <CODE>equals</CODE> properly.
101     */
102    public static final boolean areDifferent(Object o1, Object o2) {
103        return !areEqual(o1, o2);
104    }
105
106
107    /**
108     * This is a utility method that compares two Booleans when one or
109     * both of the objects might be <CODE>null</CODE>  The result of
110     * this method is determined as follows:
111     * <OL>
112     * <LI>If <CODE>b1</CODE> and <CODE>b2</CODE> are both TRUE or
113     * neither <CODE>b1</CODE> nor <CODE>b2</CODE> is TRUE,
114     * return <CODE>false</CODE>.
115     * <LI>Otherwise, return <CODE>true</CODE>.
116     * </OL>
117     * <p/>
118     * This method produces the exact logically inverted result as the
119     * {@link #areBooleansEqual(Boolean, Boolean)} method.<P>
120     */
121    public static final boolean areBooleansDifferent(Boolean b1, Boolean b2) {
122        return !areBooleansEqual(b1, b2);
123    }
124
125
126    /**
127     * Returns <CODE>true</CODE> if the specified array is not null
128     * and contains a non-null element.  Returns <CODE>false</CODE>
129     * if the array is null or if all the array elements are null.
130     */
131    public static final boolean hasNonNullElement(Object[] array) {
132        if (array != null) {
133            final int n = array.length;
134            for (int i = 0; i < n; i++) {
135                if (array[i] != null) {
136                    return true;
137                }
138            }
139        }
140        return false;
141    }
142
143    /**
144     * Returns a single string that is the concatenation of all the
145     * strings in the specified string array.  A single space is
146     * put between each string array element.  Null array elements
147     * are skipped.  If the array itself is null, the empty string
148     * is returned.  This method is guaranteed to return a non-null
149     * value, if no expections are thrown.
150     */
151    public static final String concat(String[] strs) {
152        return concat(strs, " ");  //NOTRANS
153    }
154
155    /**
156     * Returns a single string that is the concatenation of all the
157     * strings in the specified string array.  The strings are separated
158     * by the specified delimiter.  Null array elements are skipped.  If
159     * the array itself is null, the empty string is returned.  This
160     * method is guaranteed to return a non-null value, if no expections
161     * are thrown.
162     */
163    public static final String concat(String[] strs, String delim) {
164        if (strs != null) {
165            final StringBuilder buf = new StringBuilder();
166            final int n = strs.length;
167            for (int i = 0; i < n; i++) {
168                final String str = strs[i];
169                if (str != null) {
170                    buf.append(str).append(delim);
171                }
172            }
173            final int length = buf.length();
174            if (length > 0) {
175                //  Trim trailing space.
176                buf.setLength(length - 1);
177            }
178            return buf.toString();
179        }
180        else {
181            return ""; // NOTRANS
182        }
183    }
184
185    /**
186     * Returns <CODE>true</CODE> if the specified {@link String} is not
187     * <CODE>null</CODE> and has a length greater than zero.  This is
188     * a very frequently occurring check.
189     */
190    public static final boolean hasLength(String s) {
191        return (s != null && s.length() > 0);
192    }
193
194
195    /**
196     * Returns <CODE>null</CODE> if the specified string is empty or
197     * <CODE>null</CODE>.  Otherwise the string itself is returned.
198     */
199    public static final String nullifyIfEmpty(String s) {
200        return ModelUtil.hasLength(s) ? s : null;
201    }
202
203    /**
204     * Returns <CODE>null</CODE> if the specified object is null
205     * or if its <CODE>toString()</CODE> representation is empty.
206     * Otherwise, the <CODE>toString()</CODE> representation of the
207     * object itself is returned.
208     */
209    public static final String nullifyingToString(Object o) {
210        return o != null ? nullifyIfEmpty(o.toString()) : null;
211    }
212
213    /**
214     * Determines if a string has been changed.
215     *
216     * @param oldString is the initial value of the String
217     * @param newString is the new value of the String
218     * @return true If both oldString and newString are null or if they are
219     *         both not null and equal to each other.  Otherwise returns false.
220     */
221    public static boolean hasStringChanged(String oldString, String newString) {
222        if (oldString == null && newString == null) {
223            return false;
224        }
225        else if ((oldString == null && newString != null)
226                || (oldString != null && newString == null)) {
227            return true;
228        }
229        else {
230            return !oldString.equals(newString);
231        }
232    }
233
234    public static String getTimeFromLong(long diff) {
235        final String HOURS = "h";
236        final String MINUTES = "min";
237        final String SECONDS = "sec";
238
239        final long MS_IN_A_DAY = 1000 * 60 * 60 * 24;
240        final long MS_IN_AN_HOUR = 1000 * 60 * 60;
241        final long MS_IN_A_MINUTE = 1000 * 60;
242        final long MS_IN_A_SECOND = 1000;
243        diff = diff % MS_IN_A_DAY;
244        long numHours = diff / MS_IN_AN_HOUR;
245        diff = diff % MS_IN_AN_HOUR;
246        long numMinutes = diff / MS_IN_A_MINUTE;
247        diff = diff % MS_IN_A_MINUTE;
248        long numSeconds = diff / MS_IN_A_SECOND;
249        diff = diff % MS_IN_A_SECOND;
250
251        StringBuilder buf = new StringBuilder();
252        if (numHours > 0) {
253            buf.append(numHours + " " + HOURS + ", ");
254        }
255
256        if (numMinutes > 0) {
257            buf.append(numMinutes + " " + MINUTES + ", ");
258        }
259
260        buf.append(numSeconds + " " + SECONDS);
261
262        String result = buf.toString();
263        return result;
264    }
265
266
267    /**
268     * Build a List of all elements in an Iterator.
269     */
270    public static <T> List<T> iteratorAsList(Iterator<T> i) {
271        ArrayList<T> list = new ArrayList<T>(10);
272        while (i.hasNext()) {
273            list.add(i.next());
274        }
275        return list;
276    }
277
278    /**
279     * Creates an Iterator that is the reverse of a ListIterator.
280     */
281    public static <T> Iterator<T> reverseListIterator(ListIterator<T> i) {
282        return new ReverseListIterator<T>(i);
283    }
284}
285
286/**
287 * An Iterator that is the reverse of a ListIterator.
288 */
289class ReverseListIterator<T> implements Iterator<T> {
290    private ListIterator<T> _i;
291
292    ReverseListIterator(ListIterator<T> i) {
293        _i = i;
294        while (_i.hasNext())
295            _i.next();
296    }
297
298    public boolean hasNext() {
299        return _i.hasPrevious();
300    }
301
302    public T next() {
303        return _i.previous();
304    }
305
306    public void remove() {
307        _i.remove();
308    }
309
310}
311
312
313
314
315
316
317
318
319
320
321