package org.zstack.core.inventory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.stereotype.Controller; import org.zstack.header.Component; import org.zstack.header.exception.CloudRuntimeException; import org.zstack.header.search.Inventory; import java.lang.reflect.Method; import java.util.*; /** * Created with IntelliJ IDEA. * User: frank * Time: 10:06 PM * To change this template use File | Settings | File Templates. */ public class InventoryFacadeImpl implements InventoryFacade, Component { private class Info { Inventory inventory; Class<?> inventoryClass; }; private Map<Class<?>, Info> inventoryMapping = new HashMap<Class<?>, Info>(); private Info getInfo(Class<?> voClass) { Info info = inventoryMapping.get(voClass); if (info == null) { throw new IllegalArgumentException(String.format("Cannot find Inventory for class[%s], check if its responding Inventory is annotated by @Inventory ", voClass.getName())); } return info; } @Override public Object valueOf(Object vo) { return convertVOToInventory(vo); } @Override public List valueOf(Collection vos) { return convertVOsToInventories(vos); } @Override public boolean start() { try { ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true); scanner.addIncludeFilter(new AnnotationTypeFilter(Inventory.class)); scanner.addExcludeFilter(new AnnotationTypeFilter(Controller.class)); scanner.addExcludeFilter(new AnnotationTypeFilter(org.springframework.stereotype.Component.class)); for (String pkg : getBasePkgNames()) { for (BeanDefinition bd : scanner.findCandidateComponents(pkg)) { Class<?> inventoryClass = Class.forName(bd.getBeanClassName()); Inventory invat = inventoryClass.getAnnotation(Inventory.class); Info info = new Info(); info.inventory = invat; info.inventoryClass = inventoryClass; inventoryMapping.put(invat.mappingVOClass(), info); } } } catch (Exception e) { throw new CloudRuntimeException(e); } return true; } @Override public boolean stop() { return true; } public List<String> getBasePkgNames() { List<String> pkgNames = new ArrayList<String>(); pkgNames.add("org.zstack"); return pkgNames; } private Method getValueOfMethod(Class<?> inventoryClass, Class<?> voClass) throws NoSuchMethodException, SecurityException { Method valueOf = inventoryClass.getMethod("valueOf", voClass); return valueOf; } private Method getCollectionValueOfMethod(Inventory invat, Class<?> inventoryClass) throws NoSuchMethodException, SecurityException { String methodName = invat.collectionValueOfMethod(); if (methodName.equals("")) { methodName = "valueOf"; } Method valueOf = inventoryClass.getMethod(methodName, Collection.class); return valueOf; } private List convertVOsToInventories(Collection vos) { try { if (vos.isEmpty()) { return new ArrayList(); } Object first = vos.iterator().next(); Info info = getInfo(first.getClass()); Method valueOf = getCollectionValueOfMethod(info.inventory, info.inventoryClass); List ret = (List) valueOf.invoke(info.inventoryClass, vos); return ret; } catch (Exception e) { throw new CloudRuntimeException(e); } } private Object convertVOToInventory(Object vo) { try { Info info = getInfo(vo.getClass()); Method valueOf = getValueOfMethod(info.inventoryClass, vo.getClass()); Object ret = valueOf.invoke(info.inventoryClass, vo); return ret; } catch (Exception e) { throw new CloudRuntimeException(e); } } }