package org.nutz.ioc; import static org.nutz.ioc.Iocs.isIocObject; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.nutz.castor.Castors; import org.nutz.castor.FailToCastObjectException; import org.nutz.ioc.meta.IocEventSet; import org.nutz.ioc.meta.IocField; import org.nutz.ioc.meta.IocObject; import org.nutz.ioc.meta.IocValue; import org.nutz.json.Json; import org.nutz.lang.Each; import org.nutz.lang.Lang; import org.nutz.lang.Mirror; import org.nutz.lang.Strings; import org.nutz.log.Log; import org.nutz.log.Logs; public class IocLoading { private static final Log log = Logs.get(); private Set<String> supportedTypes; public IocLoading(Set<String> supportedTypes) { this.supportedTypes = supportedTypes; } private static ObjectLoadException E(Throwable e, String fmt, Object... args) { return new ObjectLoadException(String.format(fmt, args), e); } @SuppressWarnings("unchecked") public IocObject map2iobj(Map<String, Object> map) throws ObjectLoadException { final IocObject iobj = new IocObject(); if (!isIocObject(map)) { for (Entry<String, Object> en : map.entrySet()) { IocField ifld = new IocField(); ifld.setName(en.getKey()); ifld.setValue(object2value(en.getValue())); iobj.addField(ifld); } if (log.isWarnEnabled()) // TODO 移除这种兼容性 log.warn("Using *Declared* ioc-define (without type or events)!!! Pls use Standard Ioc-Define!!" + " Bean will define as:\n" + Json.toJson(iobj)); } else { Object v = map.get("type"); // type try { String typeName = (String) v; if (!Strings.isBlank(typeName)) { iobj.setType(Lang.loadClass(typeName)); } } catch (Exception e) { throw E(e, "Wrong type name: '%s'", v); } // singleton try { v = map.get("singleton"); if (null != v) iobj.setSingleton(Castors.me().castTo(v, boolean.class)); } catch (FailToCastObjectException e) { throw E(e, "Wrong singleton: '%s'", v); } // scope v = map.get("scope"); if (null != v) iobj.setScope(v.toString()); // events try { v = map.get("events"); if (null != v) { IocEventSet ies = Lang.map2Object((Map<?, ?>) v, IocEventSet.class); iobj.setEvents(ies); } } catch (Exception e) { throw E(e, "Wrong events: '%s'", v); } // args try { v = map.get("args"); if (null != v) { Lang.each(v, new Each<Object>() { public void invoke(int i, Object ele, int length) { iobj.addArg(object2value(ele)); } }); } } catch (Exception e) { throw E(e, "Wrong args: '%s'", v); } // fields try { v = map.get("fields"); if (null != v) { Map<String, Object> fields = (Map<String, Object>) v; for (Entry<String, Object> en : fields.entrySet()) { IocField ifld = new IocField(); ifld.setName(en.getKey()); ifld.setValue(object2value(en.getValue())); iobj.addField(ifld); } } } catch (Exception e) { throw E(e, "Wrong args: '%s'", v); } // factory方法 v = map.get("factory"); if (v != null && !Strings.isBlank(v.toString())) { iobj.setFactory(v.toString()); } } return iobj; } @SuppressWarnings("unchecked") IocValue object2value(Object obj) { IocValue iv = new IocValue(); // Null if (null == obj) { iv.setType("null"); return iv; } // IocValue else if (obj instanceof IocValue) { return (IocValue) obj; } // Map else if (obj instanceof Map<?, ?>) { Map<String, Object> map = (Map<String, Object>) obj; if (map.size() == 1) { Entry<String, ?> en = map.entrySet().iterator().next(); String key = en.getKey(); // support this type or not? if (supportedTypes.contains(key)) { iv.setType(key); iv.setValue(en.getValue()); return iv; } } // Inner if (map.size() > 0 && isIocObject(map)) { iv.setType(IocValue.TYPE_INNER); try { iv.setValue(map2iobj(map)); } catch (ObjectLoadException e) { throw Lang.wrapThrow(e); } return iv; } // Normal map Map<String, IocValue> newmap = new HashMap<String, IocValue>(); for (Entry<String, Object> en : map.entrySet()) { IocValue v = object2value(en.getValue()); newmap.put(en.getKey(), v); } iv.setType(IocValue.TYPE_NORMAL); iv.setValue(newmap); return iv; } // Array else if (obj.getClass().isArray()) { Object[] array = (Object[]) obj; IocValue[] ivs = new IocValue[array.length]; for (int i = 0; i < ivs.length; i++) { ivs[i] = object2value(array[i]); } iv.setType(IocValue.TYPE_NORMAL); iv.setValue(ivs); return iv; } // Collection else if (obj instanceof Collection<?>) { try { Collection<IocValue> values = (Collection<IocValue>) Mirror.me(obj).born(); Iterator<?> it = ((Collection<?>) obj).iterator(); while (it.hasNext()) { Object o = it.next(); IocValue v = object2value(o); values.add(v); } iv.setType(IocValue.TYPE_NORMAL); iv.setValue(values); return iv; } catch (Exception e) { throw Lang.wrapThrow(e); } } // Normal iv.setType(IocValue.TYPE_NORMAL); iv.setValue(obj); return iv; } }