001: /**
002: * MVEL (The MVFLEX Expression Language)
003: *
004: * Copyright (C) 2007 Christopher Brock, MVFLEX/Valhalla Project and the Codehaus
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: */package org.mvel.util;
019:
020: import org.mvel.DataTypes;
021:
022: import static java.lang.Double.parseDouble;
023: import static java.lang.Float.parseFloat;
024: import static java.lang.Integer.parseInt;
025: import static java.lang.Long.parseLong;
026: import static java.lang.String.valueOf;
027: import java.lang.reflect.Field;
028: import java.lang.reflect.Member;
029: import java.lang.reflect.Method;
030: import static java.lang.reflect.Modifier.PUBLIC;
031: import static java.lang.reflect.Modifier.isPublic;
032: import java.math.BigDecimal;
033: import java.math.BigInteger;
034: import java.util.Collection;
035: import java.util.Map;
036:
037: public class PropertyTools {
038: // private static final Pattern truePattern = compile("(on|yes|true|1|hi|high|y)");
039:
040: public static boolean isEmpty(Object o) {
041: if (o != null) {
042: if (o instanceof Object[]) {
043: return ((Object[]) o).length == 0
044: || (((Object[]) o).length == 1 && isEmpty(((Object[]) o)[0]));
045: } else {
046: return ("".equals(valueOf(o)))
047: || "null".equals(valueOf(o))
048: || (o instanceof Collection && ((Collection) o)
049: .size() == 0)
050: || (o instanceof Map && ((Map) o).size() == 0);
051: }
052: }
053: return true;
054: }
055:
056: public static Method getSetter(Class clazz, String property) {
057: property = ReflectionUtil.getSetter(property);
058:
059: for (Method meth : clazz.getMethods()) {
060: if ((meth.getModifiers() & PUBLIC) == 0
061: && meth.getParameterTypes().length != 0)
062: continue;
063:
064: if (property.equals(meth.getName())) {
065: return meth;
066: }
067: }
068:
069: return null;
070:
071: }
072:
073: public static boolean hasGetter(Field field) {
074: Method meth = getGetter(field.getDeclaringClass(), field
075: .getName());
076: return meth != null
077: && field.getType().isAssignableFrom(
078: meth.getReturnType());
079: }
080:
081: public static boolean hasSetter(Field field) {
082: Method meth = getSetter(field.getDeclaringClass(), field
083: .getName());
084: return meth != null
085: && meth.getParameterTypes().length == 1
086: && field.getType().isAssignableFrom(
087: meth.getParameterTypes()[0]);
088: }
089:
090: public static Method getGetter(Class clazz, String property) {
091: String isGet = ReflectionUtil.getIsGetter(property);
092: property = ReflectionUtil.getGetter(property);
093:
094: for (Method meth : clazz.getMethods()) {
095: if ((meth.getModifiers() & PUBLIC) == 0
096: || meth.getParameterTypes().length != 0) {
097: } else if (property.equals(meth.getName())
098: || isGet.equals(meth.getName())) {
099: return meth;
100: }
101: }
102:
103: return null;
104: }
105:
106: public static boolean isPropertyReadAndWrite(Field field) {
107: return isPublic(field.getModifiers()) || hasGetter(field)
108: && hasSetter(field);
109: }
110:
111: public static boolean isPropertyReadAndWrite(Class clazz,
112: String property) {
113: return getWritableFieldOrAccessor(clazz, property) != null
114: && getFieldOrAccessor(clazz, property) != null;
115: }
116:
117: public static Member getWritableFieldOrAccessor(Class clazz,
118: String property) {
119: Field field;
120: try {
121: if ((field = clazz.getField(property)) != null
122: && isPublic(field.getModifiers()))
123: return field;
124: } catch (NullPointerException e) {
125: return null;
126: } catch (NoSuchFieldException e) {
127: // do nothing.
128: }
129:
130: return getSetter(clazz, property);
131: }
132:
133: public static Member getFieldOrAccessor(Class clazz, String property) {
134: if (property.charAt(property.length() - 1) == ')')
135: return getGetter(clazz, property);
136:
137: try {
138: Field fld = clazz.getField(property);
139:
140: if ((fld.getModifiers() & PUBLIC) != 0)
141: return fld;
142: } catch (Exception e) {
143: // do nothing.
144: }
145: return getGetter(clazz, property);
146: }
147:
148: public static Member getFieldOrWriteAccessor(Class clazz,
149: String property) {
150: Field field;
151: try {
152: if ((field = clazz.getField(property)) != null
153: && isPublic(field.getModifiers())) {
154: return field;
155: }
156: } catch (NullPointerException e) {
157: return null;
158: } catch (NoSuchFieldException e) {
159: // do nothing.
160: }
161:
162: return getSetter(clazz, property);
163: }
164:
165: public static boolean isNumeric(Object val) {
166: if (val == null)
167: return false;
168:
169: Class clz;
170: if (val instanceof Class) {
171: clz = (Class) val;
172: } else {
173: clz = val.getClass();
174: }
175:
176: return clz == int.class || clz == long.class
177: || clz == short.class || clz == double.class
178: || clz == float.class
179: || Number.class.isAssignableFrom(clz);
180:
181: }
182:
183: public static boolean isNumber(char[] val) {
184: int len = val.length;
185: char c;
186: int i = 0;
187: if (len > 1) {
188: if (val[0] == '-')
189: i++;
190: else if (val[0] == '~') {
191: i++;
192: if (val[1] == '-')
193: i++;
194: }
195: }
196: for (; i < len; i++) {
197: if (!isDigit(c = val[i]) && c != '.')
198: return false;
199: }
200:
201: return len > 0;
202: }
203:
204: public static Object handleNumericConversion(final char[] val) {
205: switch (numericTest(val)) {
206: case DataTypes.FLOAT:
207: return parseFloat(new String(val));
208: case DataTypes.INTEGER:
209: return parseInt(new String(val));
210: case DataTypes.LONG:
211: return parseLong(new String(val));
212: case DataTypes.DOUBLE:
213: return parseDouble(new String(val));
214: case DataTypes.BIG_DECIMAL:
215: // @todo: new String() only needed for jdk1.4, remove when we move to jdk1.5
216: return new BigDecimal(new String(val));
217: default:
218: return new String(val);
219: }
220: }
221:
222: public static int numericTest(final char[] val) {
223: boolean fp = false;
224:
225: int len = val.length;
226: char c;
227: int i = 0;
228:
229: if (len > 1) {
230: if (val[0] == '-')
231: i++;
232: else if (val[0] == '~') {
233: i++;
234: if (val[1] == '-')
235: i++;
236: }
237: }
238:
239: for (; i < len; i++) {
240: if (!isDigit(c = val[i])) {
241: if (c == '.') {
242: len = 0;
243: fp = true;
244: // continue;
245: } else {
246: return -1;
247: }
248: }
249: }
250:
251: if (len > 0) {
252: if (fp) {
253: if (len > 17) {
254: return DataTypes.BIG_DECIMAL;
255: } else if (len > 15) {
256: // requires float
257: return DataTypes.FLOAT;
258: } else {
259: return DataTypes.DOUBLE;
260: }
261: } else if (len > 11) {
262: return DataTypes.BIG_DECIMAL;
263: } else if (len > 9) {
264: return DataTypes.LONG;
265: } else {
266: return DataTypes.INTEGER;
267: }
268: }
269: return -1;
270: }
271:
272: public static boolean isNumber(Object val) {
273: if (val == null)
274: return false;
275: if (val instanceof String)
276: return isNumber((String) val);
277: if (val instanceof char[])
278: return isNumber((char[]) val);
279: return val instanceof Integer || val instanceof BigDecimal
280: || val instanceof BigInteger || val instanceof Float
281: || val instanceof Double || val instanceof Long
282: || val instanceof Short || val instanceof Character;
283: }
284:
285: public static boolean isNumber(final String val) {
286: int len = val.length();
287: // char[] a = val.toCharArray();
288: char c;
289: int i = 0;
290: if (len > 1) {
291: if (val.charAt(0) == '-')
292: i++;
293: else if (val.charAt(0) == '~') {
294: i++;
295: if (val.charAt(1) == '-')
296: i++;
297: }
298: }
299: for (; i < len; i++) {
300: if (!isDigit(c = val.charAt(i)) && c != '.')
301: return false;
302: }
303:
304: return len > 0;
305: }
306:
307: public static boolean contains(Object toCompare, Object testValue) {
308: if (toCompare == null)
309: return false;
310: else if (toCompare instanceof String)
311: // @todo use String.contains once we move to jdk1.5
312: return ((String) toCompare).indexOf(valueOf(testValue)
313: .toString()) > -1;
314: else if (toCompare instanceof Collection)
315: return ((Collection) toCompare).contains(testValue);
316: else if (toCompare instanceof Map)
317: return ((Map) toCompare).containsKey(testValue);
318: else if (toCompare.getClass().isArray()) {
319: for (Object o : ((Object[]) toCompare)) {
320: if (testValue == null && o == null)
321: return true;
322: else if (o != null && o.equals(testValue))
323: return true;
324: }
325: }
326: return false;
327: }
328:
329: public static int find(char[] c, char find) {
330: for (int i = 0; i < c.length; i++)
331: if (c[i] == find)
332: return i;
333: return -1;
334: }
335:
336: public static boolean equals(char[] obj1, String obj2) {
337: for (int i = 0; i < obj1.length && i < obj2.length(); i++) {
338: if (obj1[i] == obj2.charAt(i))
339: return false;
340: }
341: return true;
342: }
343:
344: public static boolean isIdentifierPart(final int c) {
345: return ((c >= 97 && c <= 122) || (c >= 65 && c <= 90)
346: || (c >= 48 && c <= 57) || (c == '_') || (c == '$'));
347: }
348:
349: public static boolean isDigit(final int c) {
350: return c >= '0' && c <= '9';
351: }
352:
353: public static float similarity(String s1, String s2) {
354: if (s1 == null || s2 == null)
355: return s1 == null && s2 == null ? 1f : 0f;
356:
357: char[] c1 = s1.toCharArray();
358: char[] c2 = s2.toCharArray();
359:
360: char[] comp;
361: char[] against;
362:
363: float same = 0;
364: float baselength;
365:
366: int cur1 = 0;
367:
368: if (c1.length > c2.length) {
369: baselength = c1.length;
370: comp = c1;
371: against = c2;
372: } else {
373: baselength = c2.length;
374: comp = c2;
375: against = c1;
376: }
377:
378: while (cur1 < comp.length && cur1 < against.length) {
379: if (comp[cur1] == against[cur1]) {
380: same++;
381: }
382:
383: cur1++;
384: }
385:
386: return same / baselength;
387: }
388:
389: public static int findAbsoluteLast(char[] array) {
390: for (int i = array.length - 1; i >= 0; i--) {
391: if (array[i] == '.' || array[i] == '[')
392: return i;
393: }
394: return -1;
395: }
396:
397: public static Class getBaseComponentType(Class cls) {
398: while (cls.isArray()) {
399: cls = cls.getComponentType();
400: }
401: return cls;
402: }
403:
404: }
|