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