/*
* Copyright 2010 Instituto Superior Tecnico
*
* https://fenix-ashes.ist.utl.pt/
*
* This file is part of the vaadin-framework.
*
* The vaadin-framework Infrastructure 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
* 3 of the License, or (at your option) any later version.*
*
* vaadin-framework 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 vaadin-framework. If not, see .
*
*/
package pt.ist.vaadinframework.data.metamodel;
import java.beans.IntrospectionException;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import pt.ist.fenixframework.FenixFramework;
import pt.ist.fenixframework.pstm.AbstractDomainObject;
import pt.ist.vaadinframework.VaadinFrameworkLogger;
import dml.DomainClass;
import dml.Role;
import dml.Slot;
/**
* @author Pedro Santos (pedro.miguel.santos@ist.utl.pt)
*
*/
public class MetaModel implements Serializable {
private static final Map, MetaModel> modelCache =
new HashMap, MetaModel>();
private final Map descriptors = new HashMap();
/**
* @param type
*/
private Method getSetMethod(Class extends AbstractDomainObject> type, String fieldName, Class> paramType) {
try {
final String setterName = "set" + StringUtils.capitalize(fieldName);
final Method setMethod = type.getDeclaredMethod(setterName, paramType);
return setMethod;
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
}
return null;
}
private MetaModel(Class extends AbstractDomainObject> type) {
for (DomainClass clazz = FenixFramework.getDomainModel().findClass(type.getName()); clazz != null; clazz =
(DomainClass) clazz.getSuperclass()) {
for (Slot slot : clazz.getSlotsList()) {
try {
descriptors.put(slot.getName(), new SlotPropertyDescriptor(slot, type));
} catch (IntrospectionException e) {
VaadinFrameworkLogger.getLogger().error("Failed to create property descriptor for slot: " + slot.getName());
}
}
for (Role role : clazz.getRoleSlotsList()) {
try {
if (role.getName() != null && !role.getName().isEmpty()) {
descriptors.put(role.getName(), new RolePropertyDescriptor(role, type));
}
} catch (SecurityException e) {
VaadinFrameworkLogger.getLogger().error("Failed to create property descriptor for role: " + role.getName());
} catch (IntrospectionException e) {
VaadinFrameworkLogger.getLogger().error("Failed to create property descriptor for role: " + role.getName());
} catch (NoSuchMethodException e) {
VaadinFrameworkLogger.getLogger().error("Failed to create property descriptor for role: " + role.getName());
} catch (ClassNotFoundException e) {
VaadinFrameworkLogger.getLogger().error("Failed to create property descriptor for role: " + role.getName());
}
}
}
for (Method method : type.getMethods()) {
final String methodName = method.getName();
String fieldName = StringUtils.uncapitalize(methodName.substring(3, methodName.length()));
if (fieldName.equalsIgnoreCase("oid")) {
continue;
}
if (fieldName.equals("idInternal")) {
continue;
}
String replace = fieldName.replace("Count", "").replace("Set", "").replace("Iterator", "");
if (descriptors.containsKey(replace)) {
continue;
}
Method readMethod = null;
Method writeMethod = null;
if (!methodName.contains("$") && methodName.startsWith("get")) {
readMethod = method;
Class> returnType = readMethod.getReturnType();
writeMethod = getSetMethod(type, fieldName, returnType);
}
if (readMethod != null) {
java.beans.PropertyDescriptor propertyDescriptor;
try {
propertyDescriptor = new java.beans.PropertyDescriptor(fieldName, readMethod, writeMethod);
final BeanPropertyDescriptor beanPropertyDesc = new BeanPropertyDescriptor(propertyDescriptor, false);
descriptors.put(fieldName, beanPropertyDesc);
} catch (IntrospectionException e) {
VaadinFrameworkLogger.getLogger().error("Failed to create property descriptor for method : " + methodName);
}
}
}
}
/**
* @return
*/
public Collection getPropertyDescriptors() {
return Collections.unmodifiableCollection(descriptors.values());
}
/**
* @param propertyId
*/
public PropertyDescriptor getPropertyDescriptor(String propertyId) {
if (!descriptors.containsKey(propertyId)) {
int dotLocation = propertyId.indexOf('.');
if (dotLocation != -1) {
PropertyDescriptor descriptor = descriptors.get(propertyId.substring(0, dotLocation));
MetaModel model = MetaModel.findMetaModelForType(descriptor.getPropertyType());
descriptors.put(propertyId, model.getPropertyDescriptor(propertyId.substring(dotLocation + 1)));
} else {
throw new Error("could not find property: " + propertyId);
}
}
return descriptors.get(propertyId);
}
/**
* @return
*/
public Collection getPropertyIds() {
return Collections.unmodifiableCollection(descriptors.keySet());
}
public static MetaModel findMetaModelForType(Class extends AbstractDomainObject> type) {
if (!modelCache.containsKey(type)) {
modelCache.put(type, new MetaModel(type));
}
return modelCache.get(type);
}
}