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.cp; 014 015import static org.apache.juneau.internal.CollectionUtils.*; 016import java.util.*; 017import java.util.function.*; 018 019import org.apache.juneau.*; 020 021/** 022 * Utility class for instantiating a Context bean. 023 * 024 * <p> 025 * Contains either a pre-existing Context bean, or a builder for that bean. 026 * If it's a builder, then annotations can be applied to it. 027 * 028 * <h5 class='section'>See Also:</h5><ul> 029 * </ul> 030 * 031 * @param <T> The bean type. 032 */ 033public class ContextBeanCreator<T> { 034 035 /** 036 * Creator. 037 * 038 * @param <T> The bean type. 039 * @param type The bean type. 040 * @return A new creator object. 041 */ 042 public static <T> ContextBeanCreator<T> create(Class<T> type) { 043 return new ContextBeanCreator<>(type); 044 } 045 046 private Class<T> type; 047 private T impl; 048 private Context.Builder builder; 049 050 /** 051 * Constructor. 052 * 053 * @param type The bean type. 054 */ 055 protected ContextBeanCreator(Class<T> type) { 056 this.type = type; 057 } 058 059 /** 060 * Copy constructor. 061 * 062 * @param copyFrom The creator to copy from. 063 */ 064 protected ContextBeanCreator(ContextBeanCreator<T> copyFrom) { 065 this.type = copyFrom.type; 066 this.impl = copyFrom.impl; 067 this.builder = copyFrom.builder == null ? null : copyFrom.builder.copy(); 068 } 069 070 /** 071 * Sets an already instantiated object on this creator. 072 * 073 * @param value The bean to set. 074 * @return This object. 075 */ 076 @SuppressWarnings("unchecked") 077 public ContextBeanCreator<T> impl(Object value) { 078 this.impl = (T)value; 079 return this; 080 } 081 082 /** 083 * Sets the implementation type of the bean. 084 * 085 * <p> 086 * The class type must extend from {@link Context} and have a builder create method. 087 * 088 * @param value The bean type. 089 * @return This object. 090 */ 091 @SuppressWarnings("unchecked") 092 public ContextBeanCreator<T> type(Class<? extends T> value) { 093 builder = Context.createBuilder((Class<? extends Context>) value); 094 if (builder == null) 095 throw new RuntimeException("Creator for class {0} not found." + value.getName()); 096 return this; 097 } 098 099 /** 100 * Returns access to the inner builder if the builder exists and is of the specified type. 101 * 102 * @param <B> The builder class type. 103 * @param c The builder class type. 104 * @return An optional containing the builder if it exists. 105 */ 106 public <B extends Context.Builder> Optional<B> builder(Class<B> c) { 107 return optional(c.isInstance(builder) ? c.cast(builder) : null); 108 } 109 110 /** 111 * Applies an operation to the builder in this creator object. 112 * 113 * <p> 114 * Typically used to allow you to execute operations without breaking the fluent flow of the client builder. 115 * The operation is ignored if the builder isn't the specified type. 116 * 117 * @param <B> The builder class type. 118 * @param c The builder class type. 119 * @param operation The operation to apply. 120 * @return This object. 121 */ 122 public <B extends Context.Builder> ContextBeanCreator<T> builder(Class<B> c, Consumer<B> operation) { 123 if (c.isInstance(builder)) 124 operation.accept(c.cast(builder)); 125 return this; 126 } 127 128 /** 129 * Returns true if any of the annotations/appliers can be applied to the inner builder (if it has one). 130 * 131 * @param work The work to check. 132 * @return This object. 133 */ 134 public boolean canApply(AnnotationWorkList work) { 135 if (builder != null) 136 return (builder.canApply(work)); 137 return false; 138 } 139 140 /** 141 * Applies the specified annotations to all applicable serializer builders in this group. 142 * 143 * @param work The annotations to apply. 144 * @return This object. 145 */ 146 public ContextBeanCreator<T> apply(AnnotationWorkList work) { 147 if (builder != null) 148 builder.apply(work); 149 return this; 150 } 151 152 /** 153 * Creates a new copy of this creator. 154 * 155 * @return A new copy of this creator. 156 */ 157 public ContextBeanCreator<T> copy() { 158 return new ContextBeanCreator<>(this); 159 } 160 161 /** 162 * Returns the built bean. 163 * 164 * @return The built bean. 165 */ 166 @SuppressWarnings("unchecked") 167 public T create() { 168 if (impl != null) 169 return impl; 170 if (builder != null) 171 return (T)builder.build(); 172 return null; 173 } 174}