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.properties.accessor;
021
022import java.lang.reflect.Method;
023import java.util.List;
024
025import org.apache.isis.core.metamodel.facetapi.FacetHolder;
026import org.apache.isis.core.metamodel.facetapi.FacetUtil;
027import org.apache.isis.core.metamodel.facetapi.FeatureType;
028import org.apache.isis.core.metamodel.facetapi.MethodRemover;
029import org.apache.isis.core.metamodel.methodutils.MethodScope;
030import org.apache.isis.core.progmodel.facets.MethodPrefixConstants;
031import org.apache.isis.core.progmodel.facets.PropertyOrCollectionIdentifyingFacetFactoryAbstract;
032
033public class PropertyAccessorFacetFactory extends PropertyOrCollectionIdentifyingFacetFactoryAbstract {
034
035    private static final String[] PREFIXES = { MethodPrefixConstants.GET_PREFIX, MethodPrefixConstants.IS_PREFIX };
036
037    public PropertyAccessorFacetFactory() {
038        super(FeatureType.PROPERTIES_ONLY, PREFIXES);
039    }
040
041    @Override
042    public void process(final ProcessMethodContext processMethodContext) {
043        attachPropertyAccessFacetForAccessorMethod(processMethodContext);
044    }
045
046    private static void attachPropertyAccessFacetForAccessorMethod(final ProcessMethodContext processMethodContext) {
047
048        final Method accessorMethod = processMethodContext.getMethod();
049
050        processMethodContext.removeMethod(accessorMethod);
051
052        final FacetHolder property = processMethodContext.getFacetHolder();
053        FacetUtil.addFacet(new PropertyAccessorFacetViaAccessor(accessorMethod, property));
054    }
055
056    // ///////////////////////////////////////////////////////
057    // PropertyOrCollectionIdentifying
058    // ///////////////////////////////////////////////////////
059
060    @Override
061    public boolean isPropertyOrCollectionAccessorCandidate(final Method method) {
062        final String methodName = method.getName();
063        if (methodName.startsWith(MethodPrefixConstants.GET_PREFIX)) {
064            return true;
065        }
066        if (methodName.startsWith(MethodPrefixConstants.IS_PREFIX) && method.getReturnType() == boolean.class) {
067            return true;
068        }
069        return false;
070    }
071
072    /**
073     * The method way well represent a collection, but this facet factory does
074     * not have any opinion on the matter.
075     */
076    @Override
077    public boolean isCollectionAccessor(final Method method) {
078        return false;
079    }
080
081    @Override
082    public boolean isPropertyAccessor(final Method method) {
083        if (!isPropertyOrCollectionAccessorCandidate(method)) {
084            return false;
085        }
086        final Class<?> methodReturnType = method.getReturnType();
087        return isCollectionOrArray(methodReturnType);
088    }
089
090    @Override
091    public void findAndRemovePropertyAccessors(final MethodRemover methodRemover, final List<Method> methodListToAppendTo) {
092        appendMatchingMethods(methodRemover, MethodPrefixConstants.IS_PREFIX, boolean.class, methodListToAppendTo);
093        appendMatchingMethods(methodRemover, MethodPrefixConstants.GET_PREFIX, Object.class, methodListToAppendTo);
094    }
095
096    private static void appendMatchingMethods(final MethodRemover methodRemover, final String prefix, final Class<?> returnType, final List<Method> methodListToAppendTo) {
097        methodListToAppendTo.addAll(methodRemover.removeMethods(MethodScope.OBJECT, prefix, returnType, false, 0));
098    }
099
100    @Override
101    public void findAndRemoveCollectionAccessors(final MethodRemover methodRemover, final List<Method> methodListToAppendTo) {
102        // does nothing
103    }
104
105}