001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.commons.bean; 018 019import java.util.*; 020 021import org.apache.juneau.commons.reflect.*; 022 023/** 024 * Bean-modeling SPI seam that exposes marshalling-aware {@link BeanMeta} construction hooks. 025 * 026 * <p> 027 * The bean-modeling layer in {@code commons.bean} can construct a {@link BeanMeta} from a {@link Class} plus a 028 * {@link BeanConfigContext} alone, but the full marshalling-side construction path also needs to: 029 * <ul> 030 * <li>Read {@code @Marshalled} / {@code @BeanType} annotations to detect bean registration, dictionary names, 031 * and the type-property name. 032 * <li>Build a {@code BeanRegistry} for polymorphic dispatch (bean-level and per-property). 033 * <li>Walk the parent class/interface hierarchy to find an inherited dictionary name. 034 * </ul> 035 * 036 * <p> 037 * These operations require the marshalling-side {@code MarshallingContext}, so they are exposed here as SPI 038 * methods that take the marshalling context as an opaque {@link Object}. The marshalling-side implementation 039 * in {@code MarshalledBeanMetaInitializer} narrows the argument internally; the bean-modeling layer never 040 * imports the marshalling-side types. 041 * 042 * <p> 043 * The default {@link #NOOP} implementation is wired on the commons-side path and returns conservative defaults 044 * (no marshalling-side help available). {@code @BeanType} reads remain functional via the configured 045 * {@link BeanConfigContext#getAnnotationProvider()}. 046 * 047 * <h5 class='topic'>Thread safety</h5> 048 * Thread safety depends on implementation. 049 * 050 * @see BeanConfigContext.Builder#beanMetaInitializer(BeanMetaInitializer) 051 */ 052public interface BeanMetaInitializer { 053 054 /** 055 * Singleton commons-side default — no marshalling-side knowledge. 056 * 057 * <p> 058 * Returns conservative defaults: no bean dictionary, no inherited type-names, no {@code @Marshalled} reads. 059 * {@link #hasBeanRegistrationAnnotation(BeanConfigContext, ClassInfo)} still reads {@code @BeanType} via 060 * the supplied {@link BeanConfigContext#getAnnotationProvider() annotation provider}. 061 */ 062 BeanMetaInitializer NOOP = new BeanMetaInitializer() { 063 @Override 064 public boolean hasBeanRegistrationAnnotation(BeanConfigContext config, ClassInfo classInfo) { 065 return ! config.getAnnotationProvider().find(BeanType.class, classInfo).isEmpty(); 066 } 067 068 @Override 069 public String resolveTypePropertyName(BeanConfigContext config, ClassInfo classInfo) { 070 return null; 071 } 072 073 @Override 074 public String findMarshalledTypeName(BeanConfigContext config, ClassInfo classInfo) { 075 return null; 076 } 077 078 @Override 079 public BeanRegistryLookup buildBeanRegistry(Object marshallingContext, BeanFilter beanFilter, ClassInfo classInfo, BeanConfigContext config) { 080 return null; 081 } 082 083 @Override 084 public BeanRegistryLookup buildPropertyBeanRegistry(Object marshallingContext, BeanRegistryLookup parent, List<ClassInfo> dictionaryClasses) { 085 return null; 086 } 087 088 @Override 089 public String findTypeNameInParents(Object marshallingContext, ClassInfo classInfo, Class<?> rawClass) { 090 return null; 091 } 092 093 @Override 094 public BeanFilter buildBeanFilter(BeanInfo<?> cm) { 095 return null; 096 } 097 }; 098 099 /** 100 * Returns <jk>true</jk> if the supplied class has a "registered as bean" annotation (e.g. {@code @Marshalled} 101 * or {@code @BeanType}). Used to relax constructor-visibility / serializable / class-visibility checks during 102 * bean detection. 103 * 104 * @param config The bean-modeling configuration. 105 * @param classInfo The bean's class info. 106 * @return <jk>true</jk> if the class has a registration annotation. 107 */ 108 boolean hasBeanRegistrationAnnotation(BeanConfigContext config, ClassInfo classInfo); 109 110 /** 111 * Returns the marshalling-side {@code @Marshalled(typePropertyName)} value for the bean, or <jk>null</jk> if 112 * not set. Callers fall back to {@link BeanConfigContext#getBeanTypePropertyName()} when this returns <jk>null</jk>. 113 * 114 * @param config The bean-modeling configuration. 115 * @param classInfo The bean's class info. 116 * @return The resolved type property name, or <jk>null</jk>. 117 */ 118 String resolveTypePropertyName(BeanConfigContext config, ClassInfo classInfo); 119 120 /** 121 * Returns the marshalling-side {@code @Marshalled(typeName)} value for the bean, or <jk>null</jk> if not set. 122 * 123 * @param config The bean-modeling configuration. 124 * @param classInfo The bean's class info. 125 * @return The marshalled type name, or <jk>null</jk>. 126 */ 127 String findMarshalledTypeName(BeanConfigContext config, ClassInfo classInfo); 128 129 /** 130 * Builds the bean-level {@link BeanRegistryLookup} for the supplied class. Returns <jk>null</jk> on the 131 * commons-side path (no marshalling context). 132 * 133 * @param marshallingContext The marshalling-side context (as an opaque {@link Object}). Can be <jk>null</jk>. The effect is implementation-dependent — see {@code org.apache.juneau.marshall.MarshalledBeanMetaInitializer}, the sole concrete implementer of this SPI. 134 * @param beanFilter The bean filter applied to this bean meta. Can be <jk>null</jk>. The effect is implementation-dependent — see {@code org.apache.juneau.marshall.MarshalledBeanMetaInitializer}. 135 * @param classInfo The class info of the bean. Must not be <jk>null</jk>. 136 * @param config The bean-modeling configuration. Must not be <jk>null</jk>. 137 * @return The bean-level registry, or <jk>null</jk>. 138 */ 139 BeanRegistryLookup buildBeanRegistry(Object marshallingContext, BeanFilter beanFilter, ClassInfo classInfo, BeanConfigContext config); 140 141 /** 142 * Builds the per-property {@link BeanRegistryLookup} chained on top of the bean-level registry. 143 * 144 * @param marshallingContext The marshalling-side context. Must not be <jk>null</jk> on the marshalling path. 145 * @param parent The bean-level registry (chained behind the per-property one). May be <jk>null</jk>. 146 * @param dictionaryClasses The per-property dictionary class infos. Must not be <jk>null</jk>. 147 * @return The per-property registry, or <jk>null</jk> when there is no marshalling context. 148 */ 149 BeanRegistryLookup buildPropertyBeanRegistry(Object marshallingContext, BeanRegistryLookup parent, List<ClassInfo> dictionaryClasses); 150 151 /** 152 * Walks the parent classes/interfaces of {@code classInfo} and returns the first dictionary-name mapping for 153 * {@code rawClass} found in any parent's registry, or <jk>null</jk> if none. 154 * 155 * @param marshallingContext The marshalling-side context. Can be <jk>null</jk>. The effect is implementation-dependent — see {@code org.apache.juneau.marshall.MarshalledBeanMetaInitializer}. 156 * @param classInfo The bean's class info. 157 * @param rawClass The raw class to look up. 158 * @return The dictionary name found in a parent's registry, or <jk>null</jk>. 159 */ 160 String findTypeNameInParents(Object marshallingContext, ClassInfo classInfo, Class<?> rawClass); 161 162 /** 163 * Builds the marshalling-side {@link BeanFilter} for the supplied class, reading {@code @Marshalled} and 164 * {@code @BeanType} annotations. Returns <jk>null</jk> on the commons-side path (no marshalling-side 165 * filter construction is available). 166 * 167 * @param cm The bean type info. 168 * @return The bean filter, or <jk>null</jk>. 169 */ 170 BeanFilter buildBeanFilter(BeanInfo<?> cm); 171}