All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.AnnotationApplier Maven / Gradle / Ivy

// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau;

import static org.apache.juneau.common.internal.StringUtils.*;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.CollectionUtils.*;

import java.lang.annotation.*;
import java.nio.charset.*;
import java.util.*;
import java.util.stream.*;

import org.apache.juneau.annotation.*;
import org.apache.juneau.common.internal.StringUtils;
import org.apache.juneau.reflect.*;
import org.apache.juneau.svl.*;

/**
 * Class used to add properties to a context builder (e.g. {@link BeanContext.Builder}) from an annotation (e.g. {@link BeanConfig}).
 *
 * 

* Used by {@link Context.Builder#applyAnnotations(Class...)} and {@link Context.Builder#applyAnnotations(java.lang.reflect.Method...)} to apply * annotations to context beans. * *

* The following code shows the general design pattern. * *

* // The annotation applied to classes and methods. * @Target({METHOD,TYPE}) * @Retention(RUNTIME) * @ContextApply(BeanConfigAnnotationApplier.class) * public @interface BeanConfig { * * String sortProperties() default ""; * * } * * // The applier that applies the annotation to the bean context builder. * public class BeanConfigAnnotationApplier extends AnnotationApplier<BeanConfig,BeanContext.Builder> { * * // Required constructor. * public Applier(VarResolverSession vr) { * super(BeanConfig.class, BeanContext.Builder.class, vr); * } * * @Override * public void apply(AnnotationInfo<BeanConfig> annotationInfo, BeanContext.Builder builder) { * BeanConfig beanConfig = annotationInfo.getAnnotation(); * * String sortProperties = beanConfig.sortProperties(); * if (! sortProperties.isEmpty()) * builder.sortProperties(Boolean.parseBoolean(sortProperties)); * } * } * * // An annotated class. * @BeanConfig(sortProperties="true") * public class AnnotatedClass {} * * // Putting it together. * public static void main(String[] args) { * * // Create a JSON serializer with sorted properties. * Serializer serializer = JsonSerializer.create().applyAnnotations(AnnotatedClass.class).build(); * } *

* *
See Also:
    *
* * @param The annotation that this applier reads from. * @param The builder class to apply the annotation to. */ public abstract class AnnotationApplier { private final VarResolverSession vr; private final Class ca; private final Class cb; /** * Constructor. * * @param annotationClass The annotation class. * @param builderClass The annotation class. * @param vr The string resolver to use for resolving strings. */ protected AnnotationApplier(Class annotationClass, Class builderClass, VarResolverSession vr) { this.vr = vr == null ? VarResolver.DEFAULT.createSession() : vr; this.ca = annotationClass; this.cb = builderClass; } /** * Apply the specified annotation to the specified property store builder. * * @param annotationInfo The annotation. * @param builder The property store builder. */ public abstract void apply(AnnotationInfo annotationInfo, B builder); /** * Returns true if this apply can be appied to the specified builder. * * @param builder The builder to check. * @return true if this apply can be appied to the specified builder. */ public boolean canApply(Object builder) { return cb.isInstance(builder); } /** * Returns the builder class that this applier applies to. * * @return The builder class that this applier applies to. */ public Class getBuilderClass() { return cb; } /** * Returns the var resolver session for this apply. * * @return The var resolver session for this apply. */ protected VarResolverSession vr() { return vr; } /** * Resolves the specified string. * * @param in The string containing variables to resolve. * @return An optional containing the specified string if it exists, or {@link Optional#empty()} if it does not. */ protected Optional string(String in) { in = vr.resolve(in); return optional(isEmpty(in) ? null : in); } /** * Returns the specified value if it's simple name is not "void". * * @param The value to return. * @param in The value to return. * @return An optional containing the specified value. */ protected Optional> type(Class in) { return optional(in).filter(NOT_VOID); } /** * Returns the specified string array as an {@link Optional}. * *

* If the array is empty, then returns {@link Optional#empty()}. * * @param in The string array. * @return The array wrapped in an {@link Optional}. */ protected Optional strings(String[] in) { return optional(in.length == 0 ? null : Arrays.stream(in).map(x -> vr.resolve(x)).filter(StringUtils::isNotEmpty).toArray(String[]::new)); } /** * Resolves the specified string as a comma-delimited list of strings. * * @param in The CDL string containing variables to resolve. * @return An array with resolved strings. */ protected Stream stream(String[] in) { return Arrays.stream(in).map(x -> vr.resolve(x)).filter(StringUtils::isNotEmpty); } /** * Resolves the specified string as a comma-delimited list of strings. * * @param in The CDL string containing variables to resolve. * @return An array with resolved strings. */ protected Stream cdl(String in) { return Arrays.stream(split(vr.resolve(in))).filter(StringUtils::isNotEmpty); } /** * Resolves the specified string and converts it to a boolean. * * @param in The string containing variables to resolve. * @return The resolved boolean. */ public Optional bool(String in) { return string(in).map(Boolean::parseBoolean); } /** * Resolves the specified string and converts it to an int. * * @param in The string containing variables to resolve. * @param loc The annotation field name. * @return The resolved int. */ protected Optional integer(String in, String loc) { try { return string(in).map(Integer::parseInt); } catch (NumberFormatException e) { throw new ConfigException("Invalid syntax for integer on annotation @{0}({1}): {2}", ca.getSimpleName(), loc, in); } } /** * Resolves the specified string and converts it to a Charset. * * @param in The string containing variables to resolve. * @return The resolved Charset. */ protected Optional charset(String in) { return string(in).map(x -> "default".equalsIgnoreCase(x) ? Charset.defaultCharset() : Charset.forName(x)); } /** * Resolves the specified string and converts it to a Character. * * @param in The string containing variables to resolve. * @param loc The annotation field name. * @return The resolved Character. */ protected Optional character(String in, String loc) { return string(in).map(x -> toCharacter(x, loc)); } private Character toCharacter(String in, String loc) { if (in.length() != 1) throw new ConfigException("Invalid syntax for character on annotation @{0}({1}): {2}", ca.getSimpleName(), loc, in); return in.charAt(0); } /** * Returns the specified class array as an {@link Optional}. * *

* If the array is empty, then returns {@link Optional#empty()}. * * @param in The class array. * @return The array wrapped in an {@link Optional}. */ protected Optional[]> classes(Class[] in) { return optional(in.length == 0 ? null : in); } /** * Represents a no-op configuration apply. */ public static class NoOp extends AnnotationApplier { /** * Constructor. * * @param r The string resolver to use for resolving strings. */ public NoOp(VarResolverSession r) { super(Annotation.class, Object.class, r); } @Override /* ConfigApply */ public void apply(AnnotationInfo ai, Object b) {} } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy