001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau; 014 015import static org.apache.juneau.internal.CollectionUtils.*; 016import java.util.*; 017 018import org.apache.juneau.cp.*; 019import org.apache.juneau.internal.*; 020 021/** 022 * Base class for bean builders. 023 * 024 * <h5 class='section'>See Also:</h5><ul> 025 * </ul> 026 * 027 * @param <T> The bean type that the builder creates. 028 */ 029@FluentSetters 030public class BeanBuilder<T> { 031 032 private Class<? extends T> type, defaultType; 033 private T impl; 034 private final BeanStore beanStore; 035 036 /** 037 * Constructor. 038 * 039 * @param beanStore The bean store to use for creating beans. 040 * @param defaultType The default bean type that this builder creates. 041 */ 042 protected BeanBuilder(Class<? extends T> defaultType, BeanStore beanStore) { 043 this.defaultType = type = defaultType; 044 this.beanStore = beanStore; 045 } 046 047 /** 048 * Constructor. 049 * 050 * @param defaultType The type of bean being created. 051 */ 052 protected BeanBuilder(Class<? extends T> defaultType) { 053 this(defaultType, BeanStore.INSTANCE); 054 } 055 056 /** 057 * Copy constructor. 058 * 059 * @param copyFrom The bean store to copy from. 060 */ 061 protected BeanBuilder(BeanBuilder<T> copyFrom) { 062 type = copyFrom.type; 063 impl = copyFrom.impl; 064 beanStore = copyFrom.beanStore; 065 } 066 067 /** 068 * Creates the bean. 069 * 070 * @return A new bean. 071 */ 072 public T build() { 073 if (impl != null) 074 return impl; 075 if (type == null || type == defaultType) 076 return buildDefault(); 077 return creator().run(); 078 } 079 080 /** 081 * Instantiates the creator for this bean. 082 * 083 * <p> 084 * Subclasses can override this to provide specialized handling. 085 * 086 * @return The creator for this bean. 087 */ 088 protected BeanCreator<? extends T> creator() { 089 return beanStore 090 .createBean(type().orElseThrow(()->new RuntimeException("Type not specified."))) 091 .builder(BeanBuilder.class, this); 092 } 093 094 /** 095 * Creates the bean when the bean type is <jk>null</jk> or is the default value. 096 * 097 * @return A new bean. 098 */ 099 protected T buildDefault() { 100 return beanStore 101 .createBean(type().orElseThrow(()->new RuntimeException("Type not specified."))) 102 .builder(BeanBuilder.class, this) 103 .run(); 104 } 105 106 /** 107 * Overrides the bean type produced by the {@link #build()} method. 108 * 109 * <p> 110 * Use this method if you want to instantiated a bean subclass. 111 * 112 * @param value The setting value. 113 * @return This object. 114 */ 115 @SuppressWarnings("unchecked") 116 @FluentSetter 117 public BeanBuilder<T> type(Class<?> value) { 118 type = (Class<T>)value; 119 return this; 120 } 121 122 /** 123 * Returns the implementation type specified via {@link #type(Class)}. 124 * 125 * @return The implementation type specified via {@link #type(Class)}. 126 */ 127 protected Optional<Class<? extends T>> type() { 128 return optional(type); 129 } 130 131 /** 132 * Overrides the bean returned by the {@link #build()} method. 133 * 134 * <p> 135 * Use this method if you want this builder to return an already-instantiated bean. 136 * 137 * @param value The setting value. 138 * @return This object. 139 */ 140 @FluentSetter 141 @SuppressWarnings("unchecked") 142 public BeanBuilder<T> impl(Object value) { 143 this.impl = (T)value; 144 return this; 145 } 146 147 /** 148 * Returns the override bean specified via {@link #impl(Object)}. 149 * 150 * @return The override bean specified via {@link #impl(Object)}. 151 */ 152 protected Optional<T> impl() { 153 return optional(impl); 154 } 155 156 /** 157 * Returns the bean store passed in through the constructor. 158 * 159 * @return The bean store passed in through the constructor. 160 */ 161 public BeanStore beanStore() { 162 return beanStore; 163 } 164 165 // <FluentSetters> 166 167 // </FluentSetters> 168}