Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
xy.reflect.ui.util.ReflectionUIUtils Maven / Gradle / Ivy
package xy.reflect.ui.util;
import java.awt.Color;
import java.awt.Component;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JPanel;
import org.apache.commons.codec.binary.Base64;
import com.fasterxml.classmate.MemberResolver;
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.ResolvedTypeWithMembers;
import com.fasterxml.classmate.TypeResolver;
import com.fasterxml.classmate.members.ResolvedConstructor;
import com.fasterxml.classmate.members.ResolvedField;
import com.fasterxml.classmate.members.ResolvedMethod;
import com.thoughtworks.paranamer.AdaptiveParanamer;
import com.thoughtworks.paranamer.BytecodeReadingParanamer;
import com.thoughtworks.paranamer.DefaultParanamer;
import com.thoughtworks.paranamer.Paranamer;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.javabean.JavaBeanConverter;
import xy.reflect.ui.ReflectionUI;
import xy.reflect.ui.control.IFieldControlData;
import xy.reflect.ui.control.IMethodControlData;
import xy.reflect.ui.control.MethodControlDataProxy;
import xy.reflect.ui.control.swing.renderer.SwingRenderer;
import xy.reflect.ui.info.IInfo;
import xy.reflect.ui.info.ResourcePath;
import xy.reflect.ui.info.ValueReturnMode;
import xy.reflect.ui.info.field.IFieldInfo;
import xy.reflect.ui.info.filter.IInfoFilter;
import xy.reflect.ui.info.menu.AbstractMenuItem;
import xy.reflect.ui.info.menu.IMenuElement;
import xy.reflect.ui.info.menu.IMenuElementPosition;
import xy.reflect.ui.info.menu.Menu;
import xy.reflect.ui.info.menu.MenuElementKind;
import xy.reflect.ui.info.menu.MenuItemCategory;
import xy.reflect.ui.info.method.IMethodInfo;
import xy.reflect.ui.info.method.InvocationData;
import xy.reflect.ui.info.parameter.IParameterInfo;
import xy.reflect.ui.info.type.ITypeInfo;
import xy.reflect.ui.info.type.enumeration.IEnumerationItemInfo;
import xy.reflect.ui.info.type.enumeration.IEnumerationTypeInfo;
import xy.reflect.ui.info.type.iterable.IListTypeInfo;
import xy.reflect.ui.info.type.source.JavaTypeInfoSource;
import xy.reflect.ui.undo.ControlDataValueModification;
import xy.reflect.ui.undo.IModification;
import xy.reflect.ui.undo.InvokeMethodModification;
import xy.reflect.ui.undo.ModificationStack;
import xy.reflect.ui.undo.UndoOrder;
public class ReflectionUIUtils {
public static final String[] NEW_LINE_SEQUENCES = new String[] { "\r\n", "\n", "\r" };
public static final String METHOD_SIGNATURE_REGEX = "(\\s*[^ ]+\\s*)(\\s+[^ ]+\\s*)?\\(([^\\)]*)\\)\\s*";
public static File getCanonicalParent(File file) {
try {
return file.getCanonicalFile().getParentFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static List> getAncestorClasses(Class type) {
List> result = new ArrayList>();
while (type.getSuperclass() != null) {
result.add(type.getSuperclass());
type = type.getSuperclass();
}
return result;
}
public static Set> getAncestorClassesAndInterfaces(Class type) {
Set> result = new HashSet>();
List> ancestorClasses = getAncestorClasses(type);
result.addAll(ancestorClasses);
result.addAll(getSuperInterfaces(type.getInterfaces()));
for (Class ancestor : ancestorClasses) {
result.addAll(getSuperInterfaces(ancestor.getInterfaces()));
}
return result;
}
public static Set> getAncestorsAndSelfClassesAndInterfaces(Class type) {
Set> result = new HashSet>(getAncestorClassesAndInterfaces(type));
result.add(type);
return result;
}
public static Set> getSuperInterfaces(Class[] childInterfaces) {
Set> allInterfaces = new HashSet>();
for (int i = 0; i < childInterfaces.length; i++) {
allInterfaces.add(childInterfaces[i]);
allInterfaces.addAll(getSuperInterfaces(childInterfaces[i].getInterfaces()));
}
return allInterfaces;
}
public static boolean equalsOrBothNull(Object o1, Object o2) {
if (o1 == null) {
return o2 == null;
} else {
return o1.equals(o2);
}
}
public static String truncateNicely(String string, int maximumLength) {
if (string.length() <= maximumLength) {
return string;
} else {
return string.substring(0, maximumLength - 3) + "...";
}
}
public static Set getIntersection(Set s1, Set s2) {
HashSet result = new HashSet(s1);
result.retainAll(s2);
return result;
}
public static String buildMethodSignature(IMethodInfo method) {
StringBuilder result = new StringBuilder();
ITypeInfo returnType = method.getReturnValueType();
result.append(((returnType == null) ? "void" : returnType.getName()));
result.append(" " + method.getName() + "(");
List params = method.getParameters();
for (int i = 0; i < params.size(); i++) {
IParameterInfo param = params.get(i);
if (i > 0) {
result.append(", ");
}
result.append(param.getType().getName());
}
result.append(")");
return result.toString();
}
public static String extractMethodReturnTypeNameFromSignature(String methodSignature) {
Pattern pattern = Pattern.compile(METHOD_SIGNATURE_REGEX);
Matcher matcher = pattern.matcher(methodSignature);
if (!matcher.matches()) {
return null;
}
String result = matcher.group(1);
if (result != null) {
result = result.trim();
}
return result;
}
public static String extractMethodNameFromSignature(String methodSignature) {
Pattern pattern = Pattern.compile(METHOD_SIGNATURE_REGEX);
Matcher matcher = pattern.matcher(methodSignature);
if (!matcher.matches()) {
return null;
}
String result = matcher.group(2);
if (result != null) {
result = result.trim();
}
return result;
}
public static String[] extractMethodParameterTypeNamesFromSignature(String methodSignature) {
Pattern pattern = Pattern.compile(METHOD_SIGNATURE_REGEX);
Matcher matcher = pattern.matcher(methodSignature);
if (!matcher.matches()) {
return null;
}
String paramListString = matcher.group(3);
paramListString = paramListString.trim();
List result = new ArrayList(Arrays.asList(paramListString.split("\\s*,\\s*")));
result.removeAll(Collections.singletonList(""));
return result.toArray(new String[result.size()]);
}
public static List getJavaParameters(Method javaMethod) {
List result = new ArrayList();
for (int i = 0; i < javaMethod.getParameterTypes().length; i++) {
result.add(new Parameter(javaMethod, i));
}
return result;
}
public static List getJavaParameters(Constructor ctor) {
List result = new ArrayList();
for (int i = 0; i < ctor.getParameterTypes().length; i++) {
result.add(new Parameter(ctor, i));
}
return result;
}
public static String identifierToCaption(String id) {
StringBuilder result = new StringBuilder();
int i = 0;
char lastC = 0;
for (char c : id.toCharArray()) {
if (i == 0) {
result.append(Character.toUpperCase(c));
} else if (Character.isUpperCase(c) && !Character.isUpperCase(lastC)) {
result.append(" " + c);
} else if (Character.isDigit(c) && !Character.isDigit(lastC)) {
result.append(" " + c);
} else if (!Character.isLetterOrDigit(c) && Character.isLetterOrDigit(lastC)) {
result.append(" " + c);
} else {
result.append(c);
}
lastC = c;
i++;
}
return result.toString();
}
public static String getPrintedStackTrace(Throwable e) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(out));
return out.toString();
}
public static IMethodInfo getZeroParameterConstrucor(ITypeInfo type) {
return getNParametersMethod(type.getConstructors(), 0);
}
public static IMethodInfo getNParametersMethod(List methods, int n) {
for (IMethodInfo c : methods) {
if (c.getParameters().size() == n) {
return c;
}
}
return null;
}
public static IMethodInfo getZeroParameterMethod(List methods) {
return getNParametersMethod(methods, 0);
}
public static List getKeysFromValue(Map map, Object value) {
List result = new ArrayList();
for (Map.Entry entry : map.entrySet()) {
if (ReflectionUIUtils.equalsOrBothNull(entry.getValue(), value)) {
result.add(entry.getKey());
}
}
return result;
}
public static K getFirstKeyFromValue(Map map, Object value) {
List list = getKeysFromValue(map, value);
if (list.size() > 0) {
return list.get(0);
}
return null;
}
public static boolean hasFileNameExtension(String fileName, String[] extensions) {
for (String ext : extensions) {
if (ext.toLowerCase().equals(FileUtils.getFileNameExtension(fileName).toLowerCase())) {
return true;
}
}
return false;
}
public static T findMethodBySignature(List methods, String signature) {
for (T method : methods) {
String candidateMethodSignature = method.getSignature();
if (candidateMethodSignature.equals(signature)) {
return method;
}
}
return null;
}
public static T findInfoByName(List infos, String name) {
for (T info : infos) {
if (info.getName().equals(name)) {
return info;
}
}
return null;
}
public static T findInfoByCaption(List infos, String caption) {
for (T info : infos) {
if (info.getCaption().equals(caption)) {
return info;
}
}
return null;
}
public static String changeCase(String result, boolean upperElseLower, int subStringStart, int subStringEnd) {
String subString = result.substring(subStringStart, subStringEnd);
if (upperElseLower) {
subString = subString.toUpperCase();
} else {
subString = subString.toLowerCase();
}
return result.substring(0, subStringStart) + subString + result.substring(subStringEnd);
}
public static List> getJavaGenericTypeParameters(final Class type, final Member ofMember,
int methodArgumentPosition, Class parameterizedBaseClass) {
TypeResolver typeResolver = new TypeResolver();
ResolvedType resolvedType = null;
if (ofMember == null) {
resolvedType = typeResolver.resolve(type);
} else {
MemberResolver memberResolver = new MemberResolver(typeResolver);
ResolvedType declaringResolvedType = typeResolver.resolve(ofMember.getDeclaringClass());
ResolvedTypeWithMembers resolvedTypeWithMembers = memberResolver.resolve(declaringResolvedType, null, null);
if (ofMember instanceof Field) {
for (ResolvedField resolvedField : resolvedTypeWithMembers.getMemberFields()) {
if (resolvedField.getRawMember().equals(ofMember)) {
resolvedType = resolvedField.getType();
break;
}
}
} else if (ofMember instanceof Method) {
ResolvedMethod[] resolvedMethods;
if (Modifier.isStatic(ofMember.getModifiers())) {
resolvedMethods = resolvedTypeWithMembers.getStaticMethods();
} else {
resolvedMethods = resolvedTypeWithMembers.getMemberMethods();
}
for (ResolvedMethod resolvedMethod : resolvedMethods) {
if (resolvedMethod.getRawMember().equals(ofMember)) {
if (methodArgumentPosition == -1) {
resolvedType = resolvedMethod.getType();
} else {
resolvedType = resolvedMethod.getArgumentType(methodArgumentPosition);
}
break;
}
}
} else if (ofMember instanceof Constructor) {
for (ResolvedConstructor resolvedConstructor : resolvedTypeWithMembers.getConstructors()) {
if (resolvedConstructor.getRawMember().equals(ofMember)) {
if (methodArgumentPosition == -1) {
resolvedType = resolvedConstructor.getType();
} else {
resolvedType = resolvedConstructor.getArgumentType(methodArgumentPosition);
}
break;
}
}
} else {
throw new ReflectionUIError();
}
if (resolvedType == null) {
throw new ReflectionUIError();
}
}
List> result = new ArrayList>();
List resolvedTypeParameters = resolvedType.typeParametersFor(parameterizedBaseClass);
if (resolvedTypeParameters == null) {
return null;
}
for (ResolvedType classParameter : resolvedTypeParameters) {
result.add(classParameter.getErasedType());
}
return result;
}
public static Class getJavaGenericTypeParameter(final JavaTypeInfoSource javaTypeSource,
Class parameterizedBaseClass, int index) {
List> parameterClasses = getJavaGenericTypeParameters(javaTypeSource.getJavaType(),
javaTypeSource.getTypedMember(), javaTypeSource.getParameterPosition(), parameterizedBaseClass);
if (parameterClasses == null) {
return null;
}
if (parameterClasses.size() <= index) {
return null;
}
return parameterClasses.get(index);
}
public static String[] splitLines(String s) {
if (s.length() == 0) {
return new String[0];
}
return s.split(getNewLineRegex(), -1);
}
public static String getNewLineRegex() {
return stringJoin(Arrays.asList(NEW_LINE_SEQUENCES), "|");
}
public static Object indentLines(String s, String tabulation) {
String[] lines = splitLines(s);
StringBuilder result = new StringBuilder();
for (int i = 0; i < lines.length; i++) {
if (i > 0) {
result.append("\n");
}
String line = lines[i];
result.append(tabulation + line);
}
return result.toString();
}
public static String stringJoin(T[] array, String separator) {
return stringJoin(Arrays.asList(array), separator);
}
public static String stringJoin(List list, String separator) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
Object item = list.get(i);
if (i > 0) {
result.append(separator);
}
if (item == null) {
result.append("null");
} else {
result.append(item.toString());
}
}
return result.toString();
}
public static String[] getJavaParameterNames(Member owner) {
Paranamer paranamer = new AdaptiveParanamer(new DefaultParanamer(), new BytecodeReadingParanamer());
String[] parameterNames;
try {
parameterNames = paranamer.lookupParameterNames((AccessibleObject) owner, false);
} catch (Throwable t) {
return null;
}
if ((parameterNames == null) || (parameterNames.length == 0)) {
return null;
}
if (owner instanceof Constructor) {
Constructor ctor = (Constructor) owner;
Class ctorClass = ctor.getDeclaringClass();
if (ctorClass.isMemberClass()) {
if (!Modifier.isStatic(ctorClass.getModifiers())) {
if (parameterNames.length == (ctor.getParameterTypes().length - 1)) {
List tmpList = new ArrayList(Arrays.asList(parameterNames));
tmpList.add(0, "parent");
parameterNames = tmpList.toArray(new String[tmpList.size()]);
}
}
}
}
return parameterNames;
}
public static void transferStream(InputStream inputStream, OutputStream outputStream) throws IOException {
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
}
public static String formatParameterList(List parameters) {
StringBuilder result = new StringBuilder();
int iParam = 0;
for (IParameterInfo param : parameters) {
if (iParam > 0) {
if (iParam == parameters.size() - 1) {
result.append(" AND ");
} else {
result.append(", ");
}
}
result.append(param.getCaption());
iParam++;
}
return result.toString();
}
public static String escapeHTML(String string, boolean preserveNewLines) {
StringBuffer sb = new StringBuffer(string.length());
// true if last char was blank
boolean lastWasBlankChar = false;
int len = string.length();
char c;
for (int i = 0; i < len; i++) {
c = string.charAt(i);
if (c == ' ') {
// blank gets extra work,
// this solves the problem you get if you replace all
// blanks with , if you do that you loss
// word breaking
if (lastWasBlankChar) {
lastWasBlankChar = false;
sb.append(" ");
} else {
lastWasBlankChar = true;
sb.append(' ');
}
} else {
lastWasBlankChar = false;
//
// HTML Special Chars
if (c == '"')
sb.append(""");
else if (c == '&')
sb.append("&");
else if (c == '<')
sb.append("<");
else if (c == '>')
sb.append(">");
else if (c == '\n')
// Handle Newline
if (preserveNewLines) {
sb.append(" ");
} else {
sb.append(c);
}
else {
int ci = 0xffff & c;
if (ci < 160)
// nothing special only 7 Bit
sb.append(c);
else {
// Not 7 Bit use the unicode system
sb.append("");
sb.append(new Integer(ci).toString());
sb.append(';');
}
}
}
}
return sb.toString();
}
public static Color getDisabledTextBackgroundColor() {
return SwingRendererUtils.fixSeveralColorRenderingIssues(new JPanel().getBackground());
}
public static List getALlFields(Class type) {
List result = new ArrayList();
Class currentType = type;
while (currentType != null && currentType != Object.class) {
result.addAll(Arrays.asList(currentType.getDeclaredFields()));
currentType = currentType.getSuperclass();
}
return result;
}
public static String multiToSingleLine(String s) {
return s.replaceAll("\\r\\n|\\n|\\r", " ");
}
public static boolean isJavaClassMainMethod(Method javaMethod) {
if (Modifier.isStatic(javaMethod.getModifiers())) {
if (javaMethod.getReturnType().equals(void.class)) {
if (javaMethod.getName().equals("main")) {
Class[] paramTypes = javaMethod.getParameterTypes();
if (paramTypes.length == 1) {
if (paramTypes[0].equals(String[].class)) {
return true;
}
}
}
}
}
return false;
}
public static > int compareNullables(T c1, T c2) {
if (c1 == null) {
if (c2 == null) {
return 0;
} else {
return -1;
}
} else {
if (c2 == null) {
return 1;
} else {
return c1.compareTo(c2);
}
}
}
public static StackTraceElement[] createDebugStackTrace(int firstElementsToRemove) {
StackTraceElement[] result = new Exception().getStackTrace();
return Arrays.copyOfRange(result, 1 + firstElementsToRemove, result.length);
}
public static M findJavaMemberByName(M[] members, String memberName) {
for (M member : members) {
if (member.getName().equals(memberName)) {
return member;
}
}
return null;
}
public static String getQualifiedName(Field field) {
return field.getDeclaringClass().getName() + "#" + field.getName();
}
public static String getQualifiedName(Method method) {
return method.getDeclaringClass().getName() + "#" + method.getName() + "("
+ stringJoin(gatClassNames(method.getParameterTypes()), ",") + ")";
}
public static String getQualifiedName(Constructor constructor) {
return constructor.getDeclaringClass().getName() + "#" + constructor.getName() + "("
+ stringJoin(gatClassNames(constructor.getParameterTypes()), ",") + ")";
}
public static List gatClassNames(Class[] classes) {
List paramTypeNames = new ArrayList();
for (Class clazz : classes) {
paramTypeNames.add(clazz.getName());
}
return paramTypeNames;
}
public static void sortFields(List list) {
Collections.sort(list, new Comparator() {
@Override
public int compare(IFieldInfo f1, IFieldInfo f2) {
int result;
result = compareNullables(f1.getCategory(), f2.getCategory());
if (result != 0) {
return result;
}
result = compareNullables(f1.getType().getName().toUpperCase(), f2.getType().getName().toUpperCase());
if (result != 0) {
return result;
}
result = compareNullables(f1.getName(), f2.getName());
if (result != 0) {
return result;
}
return 0;
}
});
}
public static void sortMethods(List list) {
Collections.sort(list, new Comparator() {
@Override
public int compare(IMethodInfo m1, IMethodInfo m2) {
int result;
result = compareNullables(m1.getCategory(), m2.getCategory());
if (result != 0) {
return result;
}
List parameterTypeNames1 = new ArrayList();
for (IParameterInfo param : m1.getParameters()) {
parameterTypeNames1.add(param.getType().getName());
}
Collections.sort(parameterTypeNames1);
List parameterTypeNames2 = new ArrayList();
for (IParameterInfo param : m2.getParameters()) {
parameterTypeNames2.add(param.getType().getName());
}
Collections.sort(parameterTypeNames2);
result = stringJoin(parameterTypeNames1, "\n").compareTo(stringJoin(parameterTypeNames2, "\n"));
if (result != 0) {
return result;
}
String returnTypeName1;
{
if (m1.getReturnValueType() == null) {
returnTypeName1 = "";
} else {
returnTypeName1 = m1.getReturnValueType().getName();
}
}
String returnTypeName2;
{
if (m2.getReturnValueType() == null) {
returnTypeName2 = "";
} else {
returnTypeName2 = m2.getReturnValueType().getName();
}
}
result = compareNullables(returnTypeName1, returnTypeName2);
if (result != 0) {
return result;
}
result = compareNullables(m1.getName(), m2.getName());
if (result != 0) {
return result;
}
return 0;
}
});
}
public static String composeMessage(String contextMessage, String localMessage) {
if ((contextMessage == null) || (contextMessage.length() == 0)) {
return localMessage;
}
return contextMessage + " - " + localMessage;
}
public static String getPrettyErrorMessage(Throwable t) {
return new ReflectionUIError(t).toString();
}
public static boolean isOverridenBy(Method baseMethod, Method overridingMethod) {
if (!baseMethod.getDeclaringClass().isAssignableFrom(overridingMethod.getDeclaringClass())) {
return false;
}
if (!baseMethod.getName().equals(overridingMethod.getName())) {
return false;
}
if (!baseMethod.getReturnType().isAssignableFrom(overridingMethod.getReturnType())) {
return false;
}
Class[] baseMethodParamTypes = baseMethod.getParameterTypes();
Class[] overridingMethodParamTypes = overridingMethod.getParameterTypes();
if (baseMethodParamTypes.length != overridingMethodParamTypes.length) {
return false;
}
for (int iParam = 0; iParam < baseMethodParamTypes.length; iParam++) {
Class baseMethodParamType = baseMethodParamTypes[iParam];
Class overridingMethodParamType = overridingMethodParamTypes[iParam];
if (!baseMethodParamType.isAssignableFrom(overridingMethodParamType)) {
return false;
}
}
return true;
}
public static Object createDefaultInstance(ITypeInfo type) {
return createDefaultInstance(type, true);
}
public static Object createDefaultInstance(ITypeInfo type, boolean subTypeInstanceAllowed) {
try {
if (!type.isConcrete()) {
if (subTypeInstanceAllowed) {
if (ReflectionUIUtils.hasPolymorphicInstanceSubTypes(type)) {
for (ITypeInfo subType : type.getPolymorphicInstanceSubTypes()) {
try {
return createDefaultInstance(subType, true);
} catch (Throwable ignore) {
}
}
}
throw new ReflectionUIError("Cannot instanciate abstract or " + Object.class.getName() + " type");
} else {
throw new ReflectionUIError("Cannot instanciate abstract or " + Object.class.getName() + " type");
}
}
IMethodInfo constructor = getZeroParameterConstrucor(type);
if (constructor == null) {
throw new ReflectionUIError("Default constructor not found");
}
return constructor.invoke(null, new InvocationData());
} catch (Throwable t) {
throw new ReflectionUIError(
"Failed to create a default instance of type '" + type.getName() + "': " + t.toString(), t);
}
}
public static Comparator getInfosComparator(final List expectedOrderSpecification,
List initialOrder) {
final List initialOrderCopy = new ArrayList(initialOrder);
return new Comparator() {
@Override
public int compare(T o1, T o2) {
if (expectedOrderSpecification.contains(o1.getName())
&& expectedOrderSpecification.contains(o2.getName())) {
Integer index1 = new Integer(expectedOrderSpecification.indexOf(o1.getName()));
Integer index2 = new Integer(expectedOrderSpecification.indexOf(o2.getName()));
return index1.compareTo(index2);
}
if (expectedOrderSpecification.contains(o1.getName())) {
return 1;
}
if (expectedOrderSpecification.contains(o2.getName())) {
return -1;
}
Integer index1 = new Integer(initialOrderCopy.indexOf(o1));
Integer index2 = new Integer(initialOrderCopy.indexOf(o2));
return index1.compareTo(index2);
}
};
}
public static boolean hasPolymorphicInstanceSubTypes(ITypeInfo type) {
List polyTypes = type.getPolymorphicInstanceSubTypes();
return (polyTypes != null) && (polyTypes.size() > 0);
}
public static String toString(ReflectionUI reflectionUI, Object object) {
if (object == null) {
return "";
}
ITypeInfo type = reflectionUI.getTypeInfo(reflectionUI.getTypeInfoSource(object));
if (type instanceof IListTypeInfo) {
IListTypeInfo listType = (IListTypeInfo) type;
List result = new ArrayList();
for (Object item : listType.toArray(object)) {
result.add(toString(reflectionUI, item));
}
return ReflectionUIUtils.stringJoin(result, ", ");
} else {
return type.toString(object);
}
}
public static ResourcePath getIconImagePath(ReflectionUI reflectionUI, Object object) {
if (object == null) {
return null;
}
ITypeInfo type = reflectionUI.getTypeInfo(reflectionUI.getTypeInfoSource(object));
return type.getIconImagePath();
}
public static boolean canCopy(ReflectionUI reflectionUI, Object object) {
ITypeInfo type = reflectionUI.getTypeInfo(reflectionUI.getTypeInfoSource(object));
return type.canCopy(object);
}
public static Object copy(ReflectionUI reflectionUI, Object object) {
ITypeInfo type = reflectionUI.getTypeInfo(reflectionUI.getTypeInfoSource(object));
return type.copy(object);
}
public static void checkInstance(ITypeInfo type, Object object) {
if (object == null) {
return;
}
if (!type.supportsInstance(object)) {
throw new ReflectionUIError();
}
}
public static IModification finalizeParentObjectValueEditSession(IModification valueUndoModification,
boolean valueModifAccepted, ValueReturnMode valueReturnMode, boolean valueReplaced,
IModification commitModif, IInfo editSessionTarget, String editSessionTitle) {
ModificationStack parentObjectModifStack = new ModificationStack(null);
ModificationStack valueModifStack = new ModificationStack(null);
valueModifStack.pushUndo(valueUndoModification);
finalizeParentObjectValueEditSession(parentObjectModifStack, valueModifStack, valueModifAccepted,
valueReturnMode, valueReplaced, commitModif, editSessionTarget, editSessionTitle, null);
return parentObjectModifStack.toCompositeUndoModification(editSessionTarget, editSessionTitle);
}
public static boolean finalizeParentObjectValueEditSession(final ModificationStack parentObjectModifStack,
final ModificationStack valueModifStack, boolean valueModifAccepted, final ValueReturnMode valueReturnMode,
final boolean valueReplaced, final IModification commitModif, IInfo editSessionTarget,
String editSessionTitle, final Listener debugLogListener) {
if (parentObjectModifStack == null) {
throw new ReflectionUIError();
}
if (valueModifStack == null) {
throw new ReflectionUIError();
}
boolean parentObjectImpacted = false;
if (valueModifAccepted) {
if (!valueModifStack.isNull()) {
parentObjectImpacted = parentObjectModifStack.insideComposite(editSessionTarget, editSessionTitle,
UndoOrder.FIFO, new Accessor() {
@Override
public Boolean get() {
if (valueReturnMode != ValueReturnMode.CALCULATED) {
if (valueModifStack.wasInvalidated()) {
parentObjectModifStack.invalidate();
} else {
parentObjectModifStack
.pushUndo(valueModifStack.toCompositeUndoModification(null, null));
}
}
if ((valueReturnMode != ValueReturnMode.DIRECT_OR_PROXY) || valueReplaced) {
if (commitModif != null) {
if (debugLogListener != null) {
debugLogListener.handle("Executing " + commitModif);
}
parentObjectModifStack.apply(commitModif);
}
}
return true;
}
});
}
} else {
if (!valueModifStack.isNull()) {
if (valueReturnMode != ValueReturnMode.CALCULATED) {
if (!valueModifStack.wasInvalidated()) {
if (debugLogListener != null) {
debugLogListener.handle("Undoing " + valueModifStack);
}
valueModifStack.undoAll();
} else {
if (debugLogListener != null) {
debugLogListener.handle("WARNING: Cannot undo invalidated sub-modification stack: "
+ valueModifStack + "\n=> Invalidating parent modification stack");
}
parentObjectModifStack.invalidate();
parentObjectImpacted = true;
}
}
}
}
return parentObjectImpacted;
}
public static boolean canEditParentObjectValue(boolean valueImmutable, ValueReturnMode valueReturnMode,
boolean canCommit) {
if ((valueReturnMode != ValueReturnMode.CALCULATED) && !valueImmutable) {
return true;
}
if (canCommit) {
return true;
}
return false;
}
public static boolean isValueImmutable(ReflectionUI reflectionUI, Object value) {
if (value == null) {
return true;
}
ITypeInfo valueType = reflectionUI.getTypeInfo(reflectionUI.getTypeInfoSource(value));
return valueType.isImmutable();
}
public static ModificationStack findParentFormModificationStack(Component component, SwingRenderer swingRenderer) {
JPanel form = SwingRendererUtils.findParentForm(component, swingRenderer);
if (form == null) {
return null;
}
return swingRenderer.getModificationStackByForm().get(form);
}
public static void setValueThroughModificationStack(IFieldControlData data, Object newValue,
ModificationStack modifStack, IInfo modificationTarget) {
ControlDataValueModification modif = new ControlDataValueModification(data, newValue, modificationTarget);
try {
modifStack.apply(modif);
} catch (Throwable t) {
modifStack.invalidate();
throw new ReflectionUIError(t);
}
}
public static Object invokeMethodThroughModificationStack(IMethodControlData data, InvocationData invocationData,
ModificationStack modifStack, IInfo modificationTarget) {
if (data.isReadOnly()) {
return data.invoke(invocationData);
} else {
Runnable undoJob = data.getNextUpdateCustomUndoJob(invocationData);
if (undoJob != null) {
final Object[] resultHolder = new Object[1];
data = new MethodControlDataProxy(data) {
@Override
public Object invoke(InvocationData invocationData) {
return resultHolder[0] = super.invoke(invocationData);
}
};
InvokeMethodModification modif = new InvokeMethodModification(data, invocationData, modificationTarget);
try {
modifStack.apply(modif);
} catch (Throwable t) {
modifStack.invalidate();
throw new ReflectionUIError(t);
}
return resultHolder[0];
} else {
try {
Object result = data.invoke(invocationData);
return result;
} finally {
modifStack.invalidate();
}
}
}
}
public static String getDefaultMethodCaption(IMethodInfo method) {
String result = ReflectionUIUtils.identifierToCaption(method.getName());
if (method.getReturnValueType() != null) {
result = result.replaceAll("^Get ", "Show ");
}
return result;
}
public static String getDefaultFieldCaption(IFieldInfo field) {
String result = ReflectionUIUtils.identifierToCaption(field.getName());
return result;
}
public static String getDefaultListTypeCaption(IListTypeInfo listType) {
ITypeInfo itemType = listType.getItemType();
if (itemType == null) {
return "List";
} else {
return "List of " + itemType.getCaption() + " elements";
}
}
public static Listener getDebugLogListener(final ReflectionUI reflectionUI) {
return new Listener() {
@Override
public void handle(String event) {
reflectionUI.logDebug(event);
}
};
}
public static Listener getErrorLogListener(final ReflectionUI reflectionUI) {
return new Listener() {
@Override
public void handle(String event) {
reflectionUI.logError(event);
}
};
}
public static String getContructorDescription(IMethodInfo ctor) {
StringBuilder result = new StringBuilder(ctor.getCaption());
if (ctor.getParameters().size() == 0) {
result.append(" - by default");
} else {
result.append(" - specify ");
result.append(formatParameterList(ctor.getParameters()));
}
return result.toString();
}
public static String serializeToHexaText(Object object) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos;
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.flush();
byte[] binary = baos.toByteArray();
return Base64.encodeBase64String(binary);
} catch (Throwable e) {
throw new ReflectionUIError(e);
}
}
public static Object deserializeFromHexaText(String text) {
try {
byte[] binary = Base64.decodeBase64(text);
ByteArrayInputStream bais = new ByteArrayInputStream(binary);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Throwable e) {
throw new ReflectionUIError(e);
}
}
public static MenuElementKind getMenuElementKind(IMenuElement element) {
if (element instanceof Menu) {
return MenuElementKind.MENU;
} else if (element instanceof MenuItemCategory) {
return MenuElementKind.ITEM_CATEGORY;
} else if (element instanceof AbstractMenuItem) {
return MenuElementKind.ITEM;
} else {
throw new ReflectionUIError();
}
}
public static Object copyThroughSerialization(Serializable object) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
serialize(object, baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
Object copy = deserialize(bais);
return copy;
} catch (Throwable t) {
throw new ReflectionUIError("Could not copy object through serialization: " + t.toString());
}
}
public static void serialize(Object object, OutputStream out) {
try {
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(object);
} catch (Throwable t) {
throw new ReflectionUIError("Failed to serialize object: " + t.toString());
}
}
public static Object deserialize(InputStream in) {
try {
ObjectInputStream ois = new ObjectInputStream(in);
return ois.readObject();
} catch (Throwable t) {
throw new ReflectionUIError("Failed to deserialize object: " + t.toString());
}
}
protected static XStream getXStream() {
XStream result = new XStream();
result.registerConverter(new JavaBeanConverter(result.getMapper()), -20);
return result;
}
public static void saveXML(Object object, OutputStream out) {
XStream xstream = getXStream();
xstream.toXML(object, out);
}
public static void loadXML(Object object, InputStream in) {
XStream xstream = getXStream();
xstream.fromXML(in, object);
}
public static boolean equalsAccordingInfos(Object o1, Object o2, ReflectionUI reflectionUI,
IInfoFilter infoFilter) {
if (o1 == o2) {
return true;
}
if ((o1 == null) || (o2 == null)) {
return false;
}
if (ClassUtils.isPrimitiveClassOrWrapperOrString(o1.getClass())) {
return o1.equals(o2);
}
ITypeInfo type1 = reflectionUI.getTypeInfo(reflectionUI.getTypeInfoSource(o1));
ITypeInfo type2 = reflectionUI.getTypeInfo(reflectionUI.getTypeInfoSource(o2));
if (!type1.equals(type2)) {
return false;
}
if (type1.isPrimitive()) {
return o1.equals(o2);
}
for (IFieldInfo field : type1.getFields()) {
if (infoFilter.excludeField(field)) {
continue;
}
Object value1 = field.getValue(o1);
Object value2 = field.getValue(o2);
if (!equalsAccordingInfos(value1, value2, reflectionUI, infoFilter)) {
return false;
}
}
if (type1 instanceof IListTypeInfo) {
IListTypeInfo listType = (IListTypeInfo) type1;
Object[] rawList1 = listType.toArray(o1);
Object[] rawList2 = listType.toArray(o2);
if (rawList1.length != rawList2.length) {
return false;
}
for (int i = 0; i < rawList1.length; i++) {
Object item1 = rawList1[i];
Object item2 = rawList2[i];
if (!equalsAccordingInfos(item1, item2, reflectionUI, infoFilter)) {
return false;
}
}
}
if (type1 instanceof IEnumerationTypeInfo) {
IEnumerationTypeInfo enumType = (IEnumerationTypeInfo) type1;
IEnumerationItemInfo valueInfo1 = enumType.getValueInfo(o1);
IEnumerationItemInfo valueInfo2 = enumType.getValueInfo(o2);
if (!valueInfo1.getName().equals(valueInfo2.getName())) {
return false;
}
}
return true;
}
public static String formatMethodControlCaption(IMethodControlData data) {
String caption = data.getCaption();
{
if (caption.length() > 0) {
if (data.getParameters().size() > 0) {
caption += "...";
}
}
}
return caption;
}
public static String formatMethodControlTooltipText(IMethodControlData data) {
String toolTipText = formatMethodControlCaption(data);
{
if (data.getParameters().size() > 0) {
toolTipText += "\nParameter(s): " + ReflectionUIUtils.formatParameterList(data.getParameters());
}
if ((data.getOnlineHelp() != null) && (data.getOnlineHelp().trim().length() > 0)) {
toolTipText += "\nDescription: " + data.getOnlineHelp();
}
}
return toolTipText;
}
public static List getAncestors(IMenuElementPosition elementPosition) {
List result = new ArrayList();
while (elementPosition.getParent() != null) {
result.add(elementPosition.getParent());
elementPosition = elementPosition.getParent();
}
return result;
}
}