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