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
020 package org.apache.isis.core.progmodel.facets.properties.mandatory.staticmethod;
021
022 import java.lang.reflect.Method;
023
024 import org.apache.isis.core.commons.lang.NameUtils;
025 import org.apache.isis.core.metamodel.adapter.util.InvokeUtils;
026 import org.apache.isis.core.metamodel.exceptions.MetaModelException;
027 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
028 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
029 import org.apache.isis.core.metamodel.facetapi.FeatureType;
030 import org.apache.isis.core.metamodel.methodutils.MethodScope;
031 import org.apache.isis.core.progmodel.facets.MethodFinderUtils;
032 import org.apache.isis.core.progmodel.facets.MethodPrefixBasedFacetFactoryAbstract;
033 import org.apache.isis.core.progmodel.facets.MethodPrefixConstants;
034
035 public class PropertyOptionalFacetFactory extends MethodPrefixBasedFacetFactoryAbstract {
036
037 private static final String[] PREFIXES = { MethodPrefixConstants.OPTIONAL_PREFIX };
038
039 public PropertyOptionalFacetFactory() {
040 super(FeatureType.PROPERTIES_ONLY, PREFIXES);
041 }
042
043 @Override
044 public void process(final ProcessMethodContext processMethodContext) {
045
046 attachMandatoryFacetIfOptionalMethodIsFound(processMethodContext);
047 }
048
049 private static void attachMandatoryFacetIfOptionalMethodIsFound(final ProcessMethodContext processMethodContext) {
050 final Method method = processMethodContext.getMethod();
051
052 final String capitalizedName = NameUtils.javaBaseName(method.getName());
053 final Class<?> returnType = method.getReturnType();
054
055 final Class<?> cls = processMethodContext.getCls();
056 final Method optionalMethod =
057 MethodFinderUtils.findMethod(cls, MethodScope.CLASS, MethodPrefixConstants.OPTIONAL_PREFIX
058 + capitalizedName, boolean.class, NO_PARAMETERS_TYPES);
059 processMethodContext.removeMethod(optionalMethod);
060
061 if (!indicatesOptional(optionalMethod)) {
062 return;
063 }
064 if (returnType.isPrimitive()) {
065 throw new MetaModelException(cls.getName() + "#" + capitalizedName
066 + " cannot be an optional property as it is of a primitive type");
067 }
068 final FacetHolder property = processMethodContext.getFacetHolder();
069 FacetUtil.addFacet(new MandatoryFacetOptionalViaMethodForProperty(property));
070 }
071
072 private static boolean indicatesOptional(final Method method) {
073 if (method != null) {
074 Boolean optionalMethodReturnValue = null;
075 try {
076 optionalMethodReturnValue = (Boolean) InvokeUtils.invoke(method, new Object[0]);
077 } catch (final ClassCastException ex) {
078 // ignore
079 }
080 if (optionalMethodReturnValue == null) {
081 throw new MetaModelException("method " + method + " should return a boolean");
082 }
083 return optionalMethodReturnValue.booleanValue();
084 }
085 return false;
086 }
087
088 }