/*
* Copyright 2008-2009 the original author or authors.
*
* Licensed 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 net.hasor.core.info;
import net.hasor.core.AppContext;
import net.hasor.core.BindInfo;
import net.hasor.core.Hasor;
import net.hasor.core.Provider;
import net.hasor.core.utils.ExceptionUtils;
import net.hasor.core.utils.StringUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.*;
import java.util.Map.Entry;
/**
*
* @version : 2014年7月4日
* @author 赵永春(zyc@hasor.net)
*/
public class DefaultBindInfoProviderAdapter<T> extends AbstractBindInfoProviderAdapter<T> {
private Map<Integer, ParamInfo> constructorParams;
private Map<String, ParamInfo> injectProperty;
private String initMethod;
//
public DefaultBindInfoProviderAdapter() {
this.injectProperty = new HashMap<String, ParamInfo>();
this.constructorParams = new HashMap<Integer, ParamInfo>();
}
public DefaultBindInfoProviderAdapter(Class<T> bindingType) {
this();
this.setBindID(UUID.randomUUID().toString());
this.setBindType(bindingType);
}
@Override
public void setConstructor(final int index, final Class<?> paramType, final Provider<?> valueProvider) {
Hasor.assertIsNotNull(paramType, "paramType parameter is null.");
Hasor.assertIsNotNull(valueProvider, "valueProvider parameter is null.");
this.constructorParams.put(index, new ParamInfo(paramType, valueProvider));
}
@Override
public void setConstructor(final int index, final Class<?> paramType, final BindInfo<?> valueInfo) {
Hasor.assertIsNotNull(paramType, "paramType parameter is null.");
Hasor.assertIsNotNull(valueInfo, "valueInfo parameter is null.");
this.constructorParams.put(index, new ParamInfo(paramType, valueInfo));
}
@Override
public void addInject(final String property, final Provider<?> valueProvider) {
Hasor.assertIsNotNull(property, "property parameter is null.");
Hasor.assertIsNotNull(valueProvider, "valueProvider parameter is null.");
this.injectProperty.put(property, new ParamInfo(null, valueProvider));
}
@Override
public void addInject(final String property, final BindInfo<?> valueInfo) {
Hasor.assertIsNotNull(property, "paramType parameter is null.");
Hasor.assertIsNotNull(valueInfo, "valueInfo parameter is null.");
this.injectProperty.put(property, new ParamInfo(null, valueInfo));
}
//
//
private ConstructorInfo genConstructorInfo(AppContext appContext) throws NoSuchMethodException, SecurityException {
ArrayList<Integer> ints = new ArrayList<Integer>(constructorParams.keySet());
Collections.sort(ints);
//check
int size = ints.size();
if (!ints.isEmpty() && ints.get(size - 1) != (size - 1)) {
throw new java.lang.IllegalStateException("Constructor param index error.");
}
//
Class<?>[] types = new Class<?>[size];
Provider<?>[] providers = new Provider<?>[size];
for (Integer val : ints) {
ParamInfo pinfo = constructorParams.get(val);
types[val] = pinfo.paramType;
if (pinfo.useProvider) {
providers[val] = pinfo.valueProvider;
} else {
providers[val] = appContext.getProvider(pinfo.valueInfo);
}
}
return new ConstructorInfo(types, providers);
}
/**获得需要IoC的属性列表*/
public Constructor<?> getConstructor(Class<?> targetClass, AppContext appContext) throws NoSuchMethodException, SecurityException {
Class<?>[] types = genConstructorInfo(appContext).types;
return targetClass.getConstructor(types);
}
/**获得需要IoC的属性列表*/
public Provider<?>[] getConstructorParams(Class<?> targetClass, AppContext appContext) throws NoSuchMethodException, SecurityException {
return genConstructorInfo(appContext).providers;
}
/**获得需要IoC的属性列表*/
public Map<String, Provider<?>> getPropertys(AppContext appContext) {
Map<String, Provider<?>> propertys = new HashMap<String, Provider<?>>();
for (Entry<String, ParamInfo> ent : injectProperty.entrySet()) {
String propKey = ent.getKey();
ParamInfo propVal = ent.getValue();
if (propVal == null) {
continue;
}
if (propVal.useProvider) {
propertys.put(propKey, propVal.valueProvider);
} else {
propertys.put(propKey, appContext.getProvider(propVal.valueInfo));
}
}
return propertys;
}
@Override
public void initMethod(String methodName) {
this.initMethod = methodName;
}
/**获得初始化方法。*/
public Method getInitMethod(Class<?> targetClass) {
try {
if (StringUtils.isNotBlank(this.initMethod)) {
return targetClass.getMethod(this.initMethod);
}
} catch (Exception e) {
throw ExceptionUtils.toRuntimeException(e);
}
return null;
}
}
//
//
class ConstructorInfo {
public ConstructorInfo(Class<?>[] types, Provider<?>[] providers) {
this.types = types;
this.providers = providers;
}
public Class<?>[] types;
public Provider<?>[] providers;
}
class ParamInfo {
public ParamInfo(Class<?> paramType, Provider<?> valueProvider) {
this.paramType = paramType;
this.valueProvider = valueProvider;
this.useProvider = true;
}
public ParamInfo(Class<?> paramType, BindInfo<?> valueInfo) {
this.paramType = paramType;
this.valueInfo = valueInfo;
this.useProvider = false;
}
public Class<?> paramType;
public boolean useProvider;
public BindInfo<?> valueInfo;
public Provider<?> valueProvider;
}