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; 018 019import static org.apache.juneau.commons.utils.Utils.*; 020 021import java.util.*; 022 023import org.apache.juneau.cp.*; 024 025/** 026 * Base class for bean builders. 027 * 028 * 029 * @param <T> The bean type that the builder creates. 030 */ 031public class BeanBuilder<T> { 032 033 private Class<? extends T> type, defaultType; 034 private T impl; 035 private final BeanStore beanStore; 036 037 /** 038 * Copy constructor. 039 * 040 * @param copyFrom The bean store to copy from. 041 */ 042 protected BeanBuilder(BeanBuilder<T> copyFrom) { 043 type = copyFrom.type; 044 impl = copyFrom.impl; 045 beanStore = copyFrom.beanStore; 046 } 047 048 /** 049 * Constructor. 050 * 051 * @param beanStore The bean store to use for creating beans. 052 * @param defaultType The default bean type that this builder creates. 053 */ 054 protected BeanBuilder(Class<? extends T> defaultType, BeanStore beanStore) { 055 this.defaultType = type = defaultType; 056 this.beanStore = beanStore; 057 } 058 059 /** 060 * Returns the bean store passed in through the constructor. 061 * 062 * @return The bean store passed in through the constructor. 063 */ 064 public BeanStore beanStore() { 065 return beanStore; 066 } 067 068 /** 069 * Creates the bean. 070 * 071 * @return A new bean. 072 */ 073 public T build() { 074 if (nn(impl)) 075 return impl; 076 if (type == null || type == defaultType) 077 return buildDefault(); 078 return creator().run(); 079 } 080 081 /** 082 * Overrides the bean returned by the {@link #build()} method. 083 * 084 * <p> 085 * Use this method if you want this builder to return an already-instantiated bean. 086 * 087 * @param value The setting value. 088 * @return This object. 089 */ 090 @SuppressWarnings("unchecked") 091 public BeanBuilder<T> impl(Object value) { 092 impl = (T)value; 093 return this; 094 } 095 096 /** 097 * Overrides the bean type produced by the {@link #build()} method. 098 * 099 * <p> 100 * Use this method if you want to instantiated a bean subclass. 101 * 102 * @param value The setting value. 103 * @return This object. 104 */ 105 @SuppressWarnings("unchecked") 106 public BeanBuilder<T> type(Class<?> value) { 107 type = (Class<T>)value; 108 return this; 109 } 110 111 /** 112 * Creates the bean when the bean type is <jk>null</jk> or is the default value. 113 * 114 * @return A new bean. 115 */ 116 protected T buildDefault() { 117 return beanStore.createBean(type().orElseThrow(() -> new IllegalStateException("Type not specified."))).builder(BeanBuilder.class, this).run(); 118 } 119 120 /** 121 * Instantiates the creator for this bean. 122 * 123 * <p> 124 * Subclasses can override this to provide specialized handling. 125 * 126 * @return The creator for this bean. 127 */ 128 protected BeanCreator<? extends T> creator() { 129 return beanStore.createBean(type().orElseThrow(() -> new IllegalStateException("Type not specified."))).builder(BeanBuilder.class, this); 130 } 131 132 /** 133 * Returns the override bean specified via {@link #impl(Object)}. 134 * 135 * @return The override bean specified via {@link #impl(Object)}. 136 */ 137 protected Optional<T> impl() { 138 return opt(impl); 139 } 140 141 /** 142 * Returns the implementation type specified via {@link #type(Class)}. 143 * 144 * @return The implementation type specified via {@link #type(Class)}. 145 */ 146 protected Optional<Class<? extends T>> type() { 147 return opt(type); 148 } 149}