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.metamodel.facetapi; 021 022import java.beans.Introspector; 023import java.lang.reflect.Method; 024import java.util.List; 025 026import com.google.common.collect.ImmutableList; 027 028import org.apache.isis.applib.Identifier; 029import org.apache.isis.core.commons.lang.StringExtensions; 030import org.apache.isis.core.metamodel.facets.FacetFactory; 031import org.apache.isis.core.metamodel.spec.ObjectSpecification; 032 033/** 034 * Enumerates the features that a particular Facet can be applied to. 035 * 036 * <p> 037 * The class-level feature processing is typically performed by {@link FacetFactory}s 038 * pertaining to {@link #OBJECT}, performed before the processing of class members. 039 * However, {@link FacetFactory}s can also be associated with {@link #OBJECT_POST_PROCESSING}, 040 * which is run after all members have been introspected. This is useful for facets 041 * (eg the JDO <tt>Version</tt> annotation) that references class members. 042 * 043 * <p> 044 * TODO: should rationalize this and {@link ObjectSpecification#getResultType()} 045 * . Note though that we don't distinguish value properties and reference 046 * properties (and we probably shouldn't in {@link ObjectSpecification}, 047 * either). 048 */ 049public enum FeatureType { 050 051 OBJECT("Object") { 052 /** 053 * The supplied method can be null; at any rate it will be ignored. 054 */ 055 @Override 056 public Identifier identifierFor(final Class<?> type, final Method method) { 057 return Identifier.classIdentifier(type); 058 } 059 }, 060 PROPERTY("Property") { 061 @Override 062 public Identifier identifierFor(final Class<?> type, final Method method) { 063 return propertyOrCollectionIdentifierFor(type, method); 064 } 065 }, 066 COLLECTION("Collection") { 067 @Override 068 public Identifier identifierFor(final Class<?> type, final Method method) { 069 return propertyOrCollectionIdentifierFor(type, method); 070 } 071 }, 072 ACTION("Action") { 073 @Override 074 public Identifier identifierFor(final Class<?> type, final Method method) { 075 final String fullMethodName = method.getName(); 076 final Class<?>[] parameterTypes = method.getParameterTypes(); 077 return Identifier.actionIdentifier(type.getName(), fullMethodName, parameterTypes); 078 } 079 }, 080 ACTION_PARAMETER("Parameter") { 081 /** 082 * Always returns <tt>null</tt>. 083 */ 084 @Override 085 public Identifier identifierFor(final Class<?> type, final Method method) { 086 return null; 087 } 088 }, 089 OBJECT_POST_PROCESSING("Object post processing") { 090 /** 091 * The supplied method can be null; at any rate it will be ignored. 092 */ 093 @Override 094 public Identifier identifierFor(final Class<?> type, final Method method) { 095 return Identifier.classIdentifier(type); 096 } 097 }; 098 099 public final static List<FeatureType> COLLECTIONS_ONLY = ImmutableList.of(COLLECTION); 100 public final static List<FeatureType> ACTIONS_ONLY = ImmutableList.of(ACTION); 101 public final static List<FeatureType> PARAMETERS_ONLY = ImmutableList.of(ACTION_PARAMETER); 102 public final static List<FeatureType> PROPERTIES_ONLY = ImmutableList.of(PROPERTY); 103 public final static List<FeatureType> OBJECTS_ONLY = ImmutableList.of(OBJECT); 104 public final static List<FeatureType> MEMBERS = ImmutableList.of(PROPERTY, COLLECTION, ACTION); 105 public final static List<FeatureType> OBJECTS_AND_PROPERTIES = ImmutableList.of(OBJECT, PROPERTY); 106 public final static List<FeatureType> OBJECTS_AND_COLLECTIONS = ImmutableList.of(OBJECT, COLLECTION); 107 public final static List<FeatureType> OBJECTS_AND_ACTIONS = ImmutableList.of(OBJECT, ACTION); 108 public final static List<FeatureType> OBJECTS_PROPERTIES_AND_COLLECTIONS = ImmutableList.of(OBJECT, PROPERTY, COLLECTION); 109 public final static List<FeatureType> OBJECTS_POST_PROCESSING_ONLY = ImmutableList.of(OBJECT_POST_PROCESSING); 110 111 /** 112 * Use of this is discouraged; instead use multiple {@link FacetFactory}s 113 * for different features. 114 */ 115 public final static List<FeatureType> EVERYTHING_BUT_PARAMETERS = ImmutableList.of(OBJECT, PROPERTY, COLLECTION, ACTION); 116 /** 117 * Use of this is discouraged; instead use multiple {@link FacetFactory}s 118 * for different features. 119 */ 120 public final static List<FeatureType> EVERYTHING = ImmutableList.of(OBJECT, PROPERTY, COLLECTION, ACTION, ACTION_PARAMETER); 121 122 private final String name; 123 124 private FeatureType(final String name) { 125 this.name = name; 126 } 127 128 private static Identifier propertyOrCollectionIdentifierFor(final Class<?> type, final Method method) { 129 final String capitalizedName = StringExtensions.asJavaBaseName(method.getName()); 130 final String beanName = Introspector.decapitalize(capitalizedName); 131 return Identifier.propertyOrCollectionIdentifier(type.getName(), beanName); 132 } 133 134 public boolean isProperty() { 135 return this == PROPERTY; 136 } 137 138 public boolean isCollection() { 139 return this == COLLECTION; 140 } 141 142 public boolean isAction() { 143 return this == ACTION; 144 } 145 146 public boolean isActionParameter() { 147 return this == ACTION_PARAMETER; 148 } 149 150 /** 151 * Convenience. 152 */ 153 public boolean isPropertyOrCollection() { 154 return isProperty() || isCollection(); 155 } 156 157 public abstract Identifier identifierFor(Class<?> type, Method method); 158 159 @Override 160 public String toString() { 161 return name; 162 } 163 164}