/*
Created on April 25, 2014 by msekoranja
ALMA - Atacama Large Millimiter Array
(c) European Southern Observatory, 2011
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alma.acs.gui.util;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import alma.acs.util.UTCUtility;
/**
* Introspection based data formatter.
*/
public class DataFormatter {
public static int MAX_RECURSION_LEVEL = 25;
private static final SimpleDateFormat df = new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS");
private static final Object[] NULL_OBJECT_ARRAY = new Object[] { null };
public static String arrayToString(Object array) {
return arrayToString(array, "");
}
public static String arrayToString(Object array, String lineStart) {
if (array.getClass().isArray()) {
Object[] fixedArray;
StringBuffer result = new StringBuffer();
result.append(lineStart);
result.append("Array of class: ");
result.append(array.getClass().getComponentType().getName());
if (array.getClass().getComponentType().isPrimitive())
fixedArray = convertPrimitiveArray(array);
else
fixedArray = (Object[]) array;
result.append(" length: ");
result.append(fixedArray.length);
result.append("\n");
for (int i = 0; i < fixedArray.length; i++) {
result.append(lineStart);
result.append(" [");
result.append(i);
result.append("] ");
result.append(fixedArray[i].toString());
result.append("\n");
}
return result.toString();
} else
throw new IllegalArgumentException(
"array parameter is not an array");
}
public static Object[] convertPrimitiveArray(Object value) {
if (!(value.getClass().isArray() && value.getClass().getComponentType()
.isPrimitive()))
throw new IllegalArgumentException("value is not a primitive Array");
try {
Class<?> type = value.getClass().getComponentType();
Object[] retVal = null;
if (type.toString().equals("int")) {
int[] tempVal = (int[]) value;
retVal = new Integer[tempVal.length];
for (int i = 0; i < tempVal.length; i++)
retVal[i] = new Integer(tempVal[i]);
} else if (type.toString().equals("double")) {
double[] tempVal = (double[]) value;
retVal = new Double[tempVal.length];
for (int i = 0; i < tempVal.length; i++)
retVal[i] = new Double(tempVal[i]);
} else if (type.toString().equals("long")) {
long[] tempVal = (long[]) value;
retVal = new Long[tempVal.length];
for (int i = 0; i < tempVal.length; i++)
retVal[i] = new Long(tempVal[i]);
} else if (type.toString().equals("short")) {
short[] tempVal = (short[]) value;
retVal = new Short[tempVal.length];
for (int i = 0; i < tempVal.length; i++)
retVal[i] = new Short(tempVal[i]);
} else if (type.toString().equals("byte")) {
byte[] tempVal = (byte[]) value;
retVal = new Byte[tempVal.length];
for (int i = 0; i < tempVal.length; i++)
retVal[i] = new Byte(tempVal[i]);
} else if (type.toString().equals("char")) {
char[] tempVal = (char[]) value;
retVal = new Character[tempVal.length];
for (int i = 0; i < tempVal.length; i++)
retVal[i] = new Character(tempVal[i]);
} else if (type.toString().equals("float")) {
float[] tempVal = (float[]) value;
retVal = new Float[tempVal.length];
for (int i = 0; i < tempVal.length; i++)
retVal[i] = new Float(tempVal[i]);
} else if (type.toString().equals("boolean")) {
boolean[] tempVal = (boolean[]) value;
retVal = new Boolean[tempVal.length];
for (int i = 0; i < tempVal.length; i++)
retVal[i] = new Boolean(tempVal[i]);
}
return retVal;
} catch (Exception e) {
throw new IllegalArgumentException("value could not be converted");
}
}
public static String cropFromEnd(String string, int number_of_lines) {
int start = getLineStart(string, getLineCount(string) - number_of_lines);
if (start < 0)
return string;
String retVal = string.substring(
start,
string.length() - 1);
return retVal;
}
public static int getLineCount(String lines) {
int count = 0;
int pos = -1;
int maxPos = lines.length();
do {
pos = lines.indexOf(10, pos + 1);
count++;
} while ((pos > -1) && (pos < maxPos));
return count;
}
public static int getLineStart(String string, int lineNo) {
int count = 0;
int pos = -1;
int maxPos = string.length();
do {
pos = string.indexOf(10, pos + 1);
count++;
} while ((pos > -1) && (pos < maxPos) && (count < lineNo));
return pos;
}
public static String[] splitString(String stringToSplit,
String charToSplitAt) {
int end = -1;
int start = 0;
int maxPos = stringToSplit.length();
ArrayList<String> list = new ArrayList<String>();
do {
end = stringToSplit.indexOf(charToSplitAt, start);
list.add(stringToSplit.substring(start, end));
start = end + 1;
} while ((end > -1) && (end < maxPos));
String[] retVal = new String[list.size()];
list.toArray(retVal);
return retVal;
}
public static String[] splitStringByLines(String stringToSplit) {
int end = -1;
int start = 0;
int maxPos = stringToSplit.length();
ArrayList<String> list = new ArrayList<String>();
do {
end = stringToSplit.indexOf(10, start);
if (end == -1)
end = maxPos - 1;
if ((end >= 0) && (end < maxPos) && (start >= 0)
&& (start < maxPos))
list.add(stringToSplit.substring(start, end));
start = end + 1;
} while ((end > -1) && (end < maxPos - 1));
String[] retVal = new String[list.size()];
list.toArray(retVal);
return retVal;
}
public static String unpackArray(Object array) {
return unpackArray(array, "", 0, false);
}
public static String unpackArray(Object array, String lineStart) {
return unpackArray(array, lineStart, 0, false);
}
public static String unpackArray(Object array, String lineStart, int level,
boolean expand) {
StringBuffer result = new StringBuffer();
Class<?> type = array.getClass().getComponentType();
result.append("[Array of " + type + "], length = "
+ java.lang.reflect.Array.getLength(array));
Object[] list = null;
if (type.isPrimitive()) {
list = convertPrimitiveArray(array);
} else
list = (Object[]) array;
for (int i = 0; i < list.length; i++)
result.append("\n"
+ lineStart
+ " ("
+ i
+ ") "
+ unpackReturnValue(list[i], lineStart + " ", level + 1,
expand));
return result.toString();
}
/**
* Uses introspection to unpack any type of return value operations might
* return. It does that recursively to the level of max_recursion_level.
* It omits methods, such as hashCode, clone etc.
*/
public static String unpackReturnValue(Object value, String start, int level) {
return unpackReturnValue(value, start, level, false);
}
/**
* Uses introspection to unpack any type of return value operations might
* return. It does that recursively to the level of max_recursion_level.
* It omits methods, such as hashCode, clone etc.
*/
public static String unpackReturnValue(Object value, String start,
int level, boolean expand) {
StringBuffer result = new StringBuffer(500);
try {
if (value != null) {
Class<?> type = value.getClass();
if (type.isArray()) {
result.append(unpackArray(value, start, level, expand));
} else {
if ((value instanceof java.lang.String)
|| (value instanceof java.lang.Number)
|| (value instanceof java.lang.Boolean)) {
result.append(value.toString());
} else {
if (level > MAX_RECURSION_LEVEL)
return (value.getClass() + " (Recursion level exceeded)");
else {
result.append(value.toString());
if (expand) {
result.append('\n');
result.append(start);
result.append(" (" + type.getName() + ")");
java.lang.reflect.Field[] fields = type
.getFields();
for (int j = 0; j < fields.length; j++) {
if (!Modifier.isStatic(fields[j]
.getModifiers())
&& Modifier.isPublic(fields[j]
.getModifiers())) {
java.lang.reflect.Field curField = fields[j];
result.append('\n');
result.append(start);
result.append(curField.getName());
result.append(": ");
// msekoran - ACS timestamp support (this is really not clean solution)
if (curField.getName().equals(
"timeStamp")
&& curField
.getDeclaringClass()
.getName()
.equals("alma.ACSErr.Completion")) {
long javaTime = UTCUtility
.utcOmgToJava(curField
.getLong(value));
result.append(df.format(new Date(
javaTime)));
} else
result.append(unpackReturnValue(
curField.get(value), start
+ " ", level + 1,
expand));
}
}
// do not show Java Throwable method (e.g. getStackTrace)
boolean isThrowable = value instanceof Throwable;
if (!isThrowable) {
java.lang.reflect.Method[] methods = type
.getMethods();
for (int j = 0; j < methods.length; j++) {
if (java.lang.reflect.Modifier
.isPublic(methods[j]
.getModifiers())) {
java.lang.reflect.Method curMet = methods[j];
if ((curMet.getParameterTypes().length == 0)
&& ((curMet.getReturnType()
.isPrimitive()) || (level < 1))
&& (!curMet.getReturnType()
.toString()
.equals("void"))
&& (!curMet.getName()
.startsWith("_"))
&& (!curMet.getName()
.equals("hashCode"))
&& (!curMet.getName()
.equals("clone"))
&& (!curMet.getName()
.equals("getClass"))
&& (!curMet.getName()
.equals("toString")))
result.append("\n"
+ start
+ " |"
+ curMet.getName()
+ ": "
+ unpackReturnValue(
curMet.invoke(
value,
NULL_OBJECT_ARRAY),
start + " |",
level + 1,
expand));
}
}
}
}
}
}
}
return result.toString();
} else
return ("null");
} catch (Exception e) {
return (result + "\n" + start + "N/A");
}
}
public static String unpackValues(String[] names, Object[] values) {
return unpackValues(names, values, ":");
}
public static String unpackValues(String[] names, Object[] values,
String delimiter) {
return unpackValues(names, values, delimiter, false);
}
public static String unpackValues(String[] names, Object[] values,
String delimiter, boolean expand) {
StringBuffer result = new StringBuffer();
for (int i = 0; i < values.length; i++) {
result.append(" ");
result.append(names[i]);
result.append(delimiter);
result.append(" ");
result.append(unpackReturnValue(values[i], " ", 0, expand));
result.append("\n");
}
return result.toString();
}
}