001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.isis.core.progmodel.facets.param.autocomplete; 021 022import java.lang.reflect.Array; 023import java.lang.reflect.Method; 024import java.util.List; 025 026import org.apache.isis.core.commons.lang.StringExtensions; 027import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager; 028import org.apache.isis.core.metamodel.adapter.mgr.AdapterManagerAware; 029import org.apache.isis.core.metamodel.facetapi.FacetUtil; 030import org.apache.isis.core.metamodel.facetapi.FeatureType; 031import org.apache.isis.core.metamodel.facets.FacetedMethod; 032import org.apache.isis.core.metamodel.facets.FacetedMethodParameter; 033import org.apache.isis.core.metamodel.methodutils.MethodScope; 034import org.apache.isis.core.progmodel.facets.MethodFinderUtils; 035import org.apache.isis.core.progmodel.facets.MethodPrefixBasedFacetFactoryAbstract; 036import org.apache.isis.core.progmodel.facets.MethodPrefixConstants; 037 038public class ActionParameterAutoCompleteFacetFactory extends MethodPrefixBasedFacetFactoryAbstract implements AdapterManagerAware { 039 040 private static final String[] PREFIXES = {"autoComplete"}; 041 042 private AdapterManager adapterManager; 043 044 public ActionParameterAutoCompleteFacetFactory() { 045 super(FeatureType.ACTIONS_ONLY, OrphanValidation.VALIDATE, PREFIXES); 046 } 047 048 // /////////////////////////////////////////////////////// 049 // Actions 050 // /////////////////////////////////////////////////////// 051 052 @Override 053 public void process(final ProcessMethodContext processMethodContext) { 054 055 final FacetedMethod facetedMethod = processMethodContext.getFacetHolder(); 056 final List<FacetedMethodParameter> holderList = facetedMethod.getParameters(); 057 058 attachAutoCompleteFacetForParametersIfAutoCompleteNumMethodIsFound(processMethodContext, holderList); 059 060 } 061 062 private void attachAutoCompleteFacetForParametersIfAutoCompleteNumMethodIsFound(final ProcessMethodContext processMethodContext, final List<FacetedMethodParameter> parameters) { 063 064 if (parameters.isEmpty()) { 065 return; 066 } 067 068 final Method actionMethod = processMethodContext.getMethod(); 069 final Class<?>[] params = actionMethod.getParameterTypes(); 070 071 for (int i = 0; i < params.length; i++) { 072 073 final Class<?> paramType = params[i]; 074 final Class<?> arrayOfParamType = (Array.newInstance(paramType, 0)).getClass(); 075 076 Method autoCompleteMethod = findAutoCompleteNumMethodReturning(processMethodContext, i, arrayOfParamType); 077 if (autoCompleteMethod == null) { 078 autoCompleteMethod = findAutoCompleteNumMethodReturning(processMethodContext, i, List.class); 079 } 080 if (autoCompleteMethod == null) { 081 continue; 082 } 083 processMethodContext.removeMethod(autoCompleteMethod); 084 085 // add facets directly to parameters, not to actions 086 final FacetedMethodParameter paramAsHolder = parameters.get(i); 087 FacetUtil.addFacet(new ActionParameterAutoCompleteFacetViaMethod(autoCompleteMethod, paramType, paramAsHolder, getSpecificationLoader(), getAdapterManager())); 088 } 089 } 090 091 private Method findAutoCompleteNumMethodReturning(final ProcessMethodContext processMethodContext, final int i, final Class<?> paramType) { 092 093 final Class<?> cls = processMethodContext.getCls(); 094 final Method actionMethod = processMethodContext.getMethod(); 095 final String capitalizedName = StringExtensions.asCapitalizedName(actionMethod.getName()); 096 final String name = MethodPrefixConstants.AUTO_COMPLETE_PREFIX + i + capitalizedName; 097 return MethodFinderUtils.findMethod(cls, MethodScope.OBJECT, name, paramType, new Class[]{String.class}); 098 } 099 100 // /////////////////////////////////////////////////////////////// 101 // Dependencies 102 // /////////////////////////////////////////////////////////////// 103 104 @Override 105 public void setAdapterManager(final AdapterManager adapterManager) { 106 this.adapterManager = adapterManager; 107 } 108 109 private AdapterManager getAdapterManager() { 110 return adapterManager; 111 } 112 113}