/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openengsb.ui.common.util;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.openengsb.core.api.descriptor.AttributeDefinition;
import org.openengsb.core.api.descriptor.AttributeDefinition.Builder;
import org.openengsb.core.api.l10n.PassThroughStringLocalizer;
import org.openengsb.core.util.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
public final class MethodUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(MethodUtil.class);
private static DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private MethodUtil() {
}
public static Class<?>[] getAllInterfaces(Object serviceObject) {
List<Class<?>> interfaces = new ArrayList<Class<?>>();
interfaces.addAll(Arrays.asList(serviceObject.getClass().getInterfaces()));
Class<?> superClass = serviceObject.getClass().getSuperclass();
while (superClass != null) {
interfaces.addAll(Arrays.asList(superClass.getInterfaces()));
superClass = superClass.getSuperclass();
}
return interfaces.toArray(new Class<?>[interfaces.size()]);
}
public static List<AttributeDefinition> buildAttributesList(Class<?> theClass) {
List<AttributeDefinition> attributes = new ArrayList<AttributeDefinition>();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(theClass);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (propertyDescriptor.getWriteMethod() == null
|| !Modifier.isPublic(propertyDescriptor.getWriteMethod().getModifiers())
|| propertyDescriptor.getName().equals(ModelUtils.MODEL_TAIL_FIELD_NAME)) {
continue;
}
Builder builder =
AttributeDefinition.builder(new PassThroughStringLocalizer()).id(propertyDescriptor.getName())
.name(propertyDescriptor.getDisplayName())
.description(propertyDescriptor.getShortDescription());
addEnumValues(propertyDescriptor.getPropertyType(), builder);
AttributeDefinition a = builder.build();
attributes.add(a);
}
} catch (IntrospectionException ex) {
LOGGER.error("building attribute list failed", ex);
}
return attributes;
}
public static void addEnumValues(Class<?> theClass, Builder builder) {
if (theClass.isEnum()) {
Object[] enumConstants = theClass.getEnumConstants();
for (Object object : enumConstants) {
builder.option(object.toString(), object.toString());
}
}
}
@SuppressWarnings("unchecked")
public static <T> T buildBean(Class<T> beanClass, Map<String, String> values) {
try {
Object obj = beanClass.newInstance();
BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (propertyDescriptor.getWriteMethod() == null
|| !Modifier.isPublic(propertyDescriptor.getWriteMethod().getModifiers())) {
continue;
}
String value = values.get(propertyDescriptor.getName());
Object ob = convertToCorrectClass(propertyDescriptor.getPropertyType(), value);
propertyDescriptor.getWriteMethod().invoke(obj, ob);
}
return (T) obj;
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static Map<String, PropertyEditor> getRelevantProperties(final Object bean)
throws IntrospectionException {
Class<?> beanClass = bean.getClass();
BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
Iterator<PropertyDescriptor> propertyIterator = Iterators.forArray(propertyDescriptors);
Iterator<PropertyDescriptor> filtered = Iterators.filter(propertyIterator, new Predicate<PropertyDescriptor>() {
@Override
public boolean apply(PropertyDescriptor input) {
if (!input.getPropertyType().equals(String.class)) {
return false;
}
Method writeMethod = input.getWriteMethod();
if (writeMethod == null) {
return false;
}
return Modifier.isPublic(writeMethod.getModifiers());
}
});
Map<String, PropertyEditor> result = Maps.newHashMap();
while (filtered.hasNext()) {
PropertyDescriptor descriptor = filtered.next();
result.put(descriptor.getName(), descriptor.createPropertyEditor(bean));
}
return result;
}
public static Map<String, String> buildAttributeMap(Object bean) throws IntrospectionException {
Map<String, PropertyEditor> relevantProperties = getRelevantProperties(bean);
Map<String, String> result = new HashMap<String, String>();
for (Map.Entry<String, PropertyEditor> entry : relevantProperties.entrySet()) {
result.put(entry.getKey(), entry.getValue().getAsText());
}
return result;
}
public static <T> T buildBeanFromAttributeMap(Class<T> beanClass, Map<String, String> values) {
T bean;
try {
bean = beanClass.newInstance();
} catch (InstantiationException e) {
throw new IllegalArgumentException(e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
Map<String, PropertyEditor> relevantProperties;
try {
relevantProperties = getRelevantProperties(bean);
} catch (IntrospectionException e) {
throw new IllegalArgumentException(e);
}
for (Map.Entry<String, PropertyEditor> entry : relevantProperties.entrySet()) {
PropertyEditor editor = entry.getValue();
editor.setAsText(values.get(entry.getKey()));
}
return bean;
}
public enum TestEnum {
a, b, c
}
public static Object convertToCorrectClass(Class<?> type, Object value) {
if (type.isInstance(value)) {
return value;
}
if (type.isEnum()) {
type.getEnumConstants();
for (Object object : type.getEnumConstants()) {
if (object.toString().equals(value)) {
return object;
}
}
}
if (type.equals(Date.class) && String.class.isInstance(value)) {
try {
return dateFormatter.parse((String) value);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
if (type.equals(Boolean.class) && String.class.isInstance(value)) {
return Boolean.parseBoolean((String) value);
}
if (String.class.isInstance(value)) {
Constructor<?> constructor = getStringOnlyConstructor(type);
if (constructor != null) {
try {
return constructor.newInstance(value);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
return null;
}
public static Constructor<?> getStringOnlyConstructor(Class<?> type) {
try {
return type.getConstructor(String.class);
} catch (SecurityException e) {
LOGGER.error("unexpected security-exception occured", e);
return null;
} catch (NoSuchMethodException e) {
return null;
}
}
}