/* * Copyright 2014 mango.jfaster.org * * The Mango Project 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.jfaster.mango.binding; import org.jfaster.mango.annotation.Rename; import org.jfaster.mango.descriptor.ParameterDescriptor; import javax.annotation.Nullable; import java.lang.reflect.Type; import java.util.*; /** * @author ash */ public class DefaultParameterContext implements ParameterContext { /** * 位置到重命名后的变量名的映射 */ private final Map<Integer, String> positionToNameMap = new HashMap<Integer, String>(); /** * 参数名到参数类型的映射 */ private final Map<String, Type> nameToTypeMap = new LinkedHashMap<String, Type>(); private final List<ParameterDescriptor> parameterDescriptors = new ArrayList<ParameterDescriptor>(); private DefaultParameterContext(List<ParameterDescriptor> parameterDescriptors) { for (int i = 0; i < parameterDescriptors.size(); i++) { ParameterDescriptor pd = parameterDescriptors.get(i); Rename renameAnno = pd.getAnnotation(Rename.class); String parameterName = renameAnno != null ? renameAnno.value() : // 优先使用注解中的名字 pd.getName(); nameToTypeMap.put(parameterName, pd.getType()); int position = pd.getPosition(); positionToNameMap.put(position, parameterName); this.parameterDescriptors.add(pd); } } public static DefaultParameterContext create(List<ParameterDescriptor> parameterDescriptors) { return new DefaultParameterContext(parameterDescriptors); } @Override public String getParameterNameByPosition(int position) { String name = positionToNameMap.get(position); if (name == null) { throw new IllegalStateException("parameter name can not be found by position [" + position + "]"); } return name; } @Override public BindingParameterInvoker getBindingParameterInvoker(BindingParameter bindingParameter) { String parameterName = bindingParameter.getParameterName(); Type type = nameToTypeMap.get(parameterName); if (type == null) { throw new BindingException("Parameter '" + BindingParameter.create(bindingParameter.getParameterName(), "", null) + "' not found, available root parameters are " + transToBindingParameters(nameToTypeMap.keySet())); } return FunctionalBindingParameterInvoker.create(type, bindingParameter); } @Override public List<ParameterDescriptor> getParameterDescriptors() { return parameterDescriptors; } @Override @Nullable public BindingParameter tryExpandBindingParameter(BindingParameter bindingParameter) { if (!nameToTypeMap.containsKey(bindingParameter.getParameterName())) { // 根参数不存在才扩展 BindingParameter newBindingParameter = bindingParameter.rightShift(); List<String> parameterNames = new ArrayList<String>(); for (Map.Entry<String, Type> entry : nameToTypeMap.entrySet()) { Type type = entry.getValue(); try { FunctionalBindingParameterInvoker.create(type, newBindingParameter); } catch (BindingException e) { // 异常说明扩展失败 continue; } parameterNames.add(entry.getKey()); } int num = parameterNames.size(); if (num > 0) { if (num != 1) { throw new BindingException("Root parameters " + transToBindingParameters(parameterNames) + " has the same property '" + newBindingParameter.getPropertyPath() + "', so can't auto expand"); } return BindingParameter.create( parameterNames.get(0), newBindingParameter.getPropertyPath(), newBindingParameter.getJdbcType()); } } return null; } private Set<BindingParameter> transToBindingParameters(Collection<String> parameterNames) { Set<BindingParameter> rs = new LinkedHashSet<BindingParameter>(); for (String parameterName : parameterNames) { rs.add(BindingParameter.create(parameterName, "", null)); } return rs; } }