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