/* * 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.invoker.GetterInvoker; import org.jfaster.mango.invoker.InvokerCache; import org.jfaster.mango.invoker.UnreachablePropertyException; import org.jfaster.mango.util.NestedProperty; import org.jfaster.mango.util.PropertyTokenizer; import org.jfaster.mango.util.reflect.TypeToken; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; /** * @author ash */ public class FunctionalBindingParameterInvoker implements BindingParameterInvoker { private final Type targetType; private final BindingParameter bindingParameter; private final List<GetterInvoker> invokers; private FunctionalBindingParameterInvoker(Type originalType, BindingParameter bindingParameter) { this.bindingParameter = bindingParameter; invokers = new ArrayList<GetterInvoker>(); Type currentType = originalType; Class<?> rawType = TypeToken.of(currentType).getRawType(); PropertyTokenizer prop = new PropertyTokenizer(bindingParameter.getPropertyPath()); while (prop.hasCurrent()) { String propertyName = prop.getName(); GetterInvoker invoker = InvokerCache.getGetterInvoker(rawType, propertyName); invokers.add(invoker); currentType = invoker.getReturnType(); rawType = TypeToken.of(currentType).getRawType(); prop = prop.next(); } targetType = currentType; } public static FunctionalBindingParameterInvoker create( Type originalType, BindingParameter bindingParameter) { try { FunctionalBindingParameterInvoker invokerGroup = new FunctionalBindingParameterInvoker(originalType, bindingParameter); return invokerGroup; } catch (UnreachablePropertyException e) { throw new BindingException("Parameter '" + bindingParameter + "' can't be readable", e); } } @Override public Type getTargetType() { return targetType; } @Override public Object invoke(Object obj) { Object r = obj; int size = invokers.size(); for (int i = 0; i < size; i++) { if (r == null) { NestedProperty np = new NestedProperty(); for (int j = 0; j < i; j++) { np.append(invokers.get(j).getName()); } BindingParameter bp = BindingParameter.create(bindingParameter.getParameterName(), np.getNestedProperty(), null); throw new BindingException("Parameter '" + bp + "' is null"); } r = invokers.get(i).invoke(r); } return r; } @Override public BindingParameter getBindingParameter() { return bindingParameter; } }