/** * Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org> * Copyright (C) 2012 Google, Inc. * * 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 org.onebusaway.federations.annotations; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import org.onebusaway.exceptions.ServiceException; /** * This factory can be used to examine a Method signature and create an * appropriate {@link FederatedServiceMethodInvocationHandler} based on method * annotations. See the list of supported annotations below. * * @author bdferris * @see FederatedByAgencyIdMethod * @see FederatedByAggregateMethod * @see FederatedByBoundsMethod * @see FederatedByCoordinateBoundsMethod * @see FederatedByCoordinatePointsMethod * @see FederatedByEntityIdMethod * @see FederatedByEntityIdsMethod * @see FederatedByLocationMethod */ public class FederatedServiceMethodInvocationHandlerFactory { public FederatedServiceMethodInvocationHandler getHandlerForMethod( Method method) { FederatedByAgencyIdMethod byAgency = method.getAnnotation(FederatedByAgencyIdMethod.class); if (byAgency != null) return new FederatedByAgencyIdMethodInvocationHandlerImpl(method, byAgency.argument(), byAgency.propertyExpression()); FederatedByAnyEntityIdMethod byAnyEntityId = method.getAnnotation(FederatedByAnyEntityIdMethod.class); if (byAnyEntityId != null) return new FederatedByAnyEntityIdMethodInvocationHandlerImpl(method, byAnyEntityId.argument(), byAnyEntityId.properties(), byAnyEntityId.agencyIdProperties()); FederatedByEntityIdMethod ann0 = method.getAnnotation(FederatedByEntityIdMethod.class); if (ann0 != null) return new FederatedByEntityIdMethodInvocationHandlerImpl(method, ann0.argument(), ann0.propertyExpression()); FederatedByEntityIdsMethod ann1 = method.getAnnotation(FederatedByEntityIdsMethod.class); if (ann1 != null) return new FederatedByEntityIdsMethodInvocationHandlerImpl( ann1.argument()); FederatedByBoundsMethod ann2 = method.getAnnotation(FederatedByBoundsMethod.class); if (ann2 != null) return new FederatedByBoundsMethodInvocationHandlerImpl( ann2.lat1Argument(), ann2.lon1Argument(), ann2.lat2Argument(), ann2.lon2Argument()); FederatedByLocationMethod ann3 = method.getAnnotation(FederatedByLocationMethod.class); if (ann3 != null) return new FederatedByLocationMethodInvocationHandlerImpl( ann3.latArgument(), ann3.lonArgument()); FederatedByAggregateMethod ann4 = method.getAnnotation(FederatedByAggregateMethod.class); if (ann4 != null) { EMethodAggregationType aggregationType = getAggregationTypeForMethod(method); return new FederatedByAggregateMethodInvocationHandlerImpl( aggregationType); } FederatedByCoordinateBoundsMethod ann5 = method.getAnnotation(FederatedByCoordinateBoundsMethod.class); if (ann5 != null) return new FederatedByCoordinateBoundsMethodInvocationHandlerImpl(method, ann5.argument(), ann5.propertyExpression()); FederatedByCoordinatePointsMethod ann6 = method.getAnnotation(FederatedByCoordinatePointsMethod.class); if (ann6 != null) { int[] argumentIndices = ann6.arguments(); String[] expressions = ann6.propertyExpressions(); if (expressions.length == 0) expressions = new String[argumentIndices.length]; return new FederatedByCoordinatePointsMethodInvocationHandlerImpl(method, argumentIndices, expressions); } FederatedByCustomMethod ann7 = method.getAnnotation(FederatedByCustomMethod.class); if (ann7 != null) { Class<? extends FederatedServiceMethodInvocationHandler> handlerClass = ann7.handler(); try { return handlerClass.newInstance(); } catch (Exception ex) { throw new ServiceException( "error creating FederatedServiceMethodInvocationHandler of type " + handlerClass, ex); } } throw new IllegalArgumentException( "No FederatedService method annotation for method: " + method); } private EMethodAggregationType getAggregationTypeForMethod(Method method) { Class<?> returnType = method.getReturnType(); if (List.class.isAssignableFrom(returnType)) return EMethodAggregationType.LIST; if (Map.class.isAssignableFrom(returnType)) return EMethodAggregationType.MAP; throw new IllegalArgumentException("unsupported aggregation type: " + returnType.getName()); } }