001/* 002 * Copyright 2023 the original author or authors. 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.cuioss.tools.property; 017 018import static java.util.Objects.requireNonNull; 019 020import java.beans.PropertyDescriptor; 021 022import de.cuioss.tools.lang.MoreObjects; 023import de.cuioss.tools.logging.CuiLogger; 024import de.cuioss.tools.reflect.MoreReflection; 025import lombok.Getter; 026import lombok.RequiredArgsConstructor; 027 028/** 029 * Defines the read write permissions for a given property. It is defined for 030 * properties java Bean properties. 031 * 032 * @author Oliver Wolff 033 */ 034@RequiredArgsConstructor 035public enum PropertyReadWrite { 036 037 /** The corresponding property is read only. */ 038 READ_ONLY(true, false), 039 /** The property can be read and written to. */ 040 READ_WRITE(true, true), 041 /** The property can only be written to. */ 042 WRITE_ONLY(false, true), 043 /** The property can neither be read nor written to. */ 044 NONE(false, false); 045 046 private static final CuiLogger log = new CuiLogger(PropertyReadWrite.class); 047 048 @Getter 049 private final boolean readable; 050 051 @Getter 052 private final boolean writeable; 053 054 /** 055 * Resolves {@link PropertyReadWrite} for a given property with 056 * {@link MoreReflection} 057 * 058 * @param beanType to be checked, must not be null 059 * @param propertyName to be checked, must not be null 060 * @return the corresponding {@link PropertyReadWrite} for a given property 061 */ 062 public static PropertyReadWrite resolveForBean(final Class<?> beanType, final String propertyName) { 063 final var readable = MoreReflection.retrieveAccessMethod(beanType, propertyName).isPresent(); 064 final var writeable = !MoreReflection.retrieveWriteMethodCandidates(beanType, propertyName).isEmpty(); 065 if (readable && writeable) { 066 return READ_WRITE; 067 } 068 if (readable) { 069 return READ_ONLY; 070 } 071 if (writeable) { 072 return WRITE_ONLY; 073 } 074 return NONE; 075 } 076 077 /** 078 * Resolves {@link PropertyReadWrite} form the given {@link PropertyDescriptor}. 079 * If this provides unclear result it will call 080 * {@link #resolveForBean(Class, String)} 081 * 082 * @param descriptor to be read from 083 * @param beanType to be checked, must not be null 084 * @param propertyName to be checked, must not be null 085 * @return the corresponding {@link PropertyReadWrite} for a given property 086 */ 087 public static PropertyReadWrite fromPropertyDescriptor(PropertyDescriptor descriptor, final Class<?> beanType, 088 final String propertyName) { 089 requireNonNull(descriptor); 090 if (MoreObjects.allNonNull(descriptor.getReadMethod(), descriptor.getWriteMethod())) { 091 return READ_WRITE; 092 } 093 log.debug( 094 "PropertyDescriptor '%s' does not describe a standard bean-structure for property '%s' on type '%s', switching to reflection", 095 descriptor, propertyName, beanType); 096 return resolveForBean(beanType, propertyName); 097 } 098}