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