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;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import org.apache.juneau.commons.bean.*;
022import org.apache.juneau.commons.reflect.*;
023import org.apache.juneau.commons.svl.*;
024
025/**
026 * Utility classes and methods for the {@link BeanConfig @BeanConfig} annotation.
027 *
028 * <p>
029 * Houses the {@link Applier} that pushes {@link BeanConfig @BeanConfig} attributes into a
030 * {@link MarshallingContext.Builder}. The annotation itself lives in
031 * {@code juneau-commons} (in {@link BeanConfig}), but
032 * the application logic lives here in {@code juneau-marshall} because it depends on
033 * marshall-layer types ({@link AnnotationApplier}, {@link MarshallingContext} builder APIs,
034 * {@link VarResolverSession}, etc.).
035 *
036 * <p>
037 * Because {@link BeanConfig @BeanConfig} cannot carry a {@link ContextApply @ContextApply}
038 * meta-annotation (that annotation lives in {@code juneau-marshall} and cannot be referenced
039 * from {@code juneau-commons}), {@link AnnotationWorkList} special-cases the
040 * {@link BeanConfig} annotation type and instantiates this {@link Applier} directly.
041 */
042public class BeanConfigAnnotation {
043
044   /**
045    * Prevents instantiation.
046    */
047   private BeanConfigAnnotation() {}
048
049   /**
050    * Applies {@link BeanConfig} annotations to a {@link MarshallingContext.Builder}.
051    */
052   public static class Applier extends AnnotationApplier<BeanConfig,MarshallingContext.Builder> {
053
054      /**
055       * Constructor.
056       *
057       * @param vr The resolver for resolving values in annotations. Must not be <jk>null</jk>.
058       */
059      public Applier(VarResolverSession vr) {
060         super(BeanConfig.class, MarshallingContext.Builder.class, vr);
061      }
062
063      @Override
064      public void apply(AnnotationInfo<BeanConfig> ai, MarshallingContext.Builder b) {
065         BeanConfig a = ai.inner();
066
067         // @formatter:off
068         string(a.beanClassVisibility()).map(Visibility::valueOf).ifPresent(b::beanClassVisibility);
069         string(a.beanConstructorVisibility()).map(Visibility::valueOf).ifPresent(b::beanConstructorVisibility);
070         string(a.beanFieldVisibility()).map(Visibility::valueOf).ifPresent(b::beanFieldVisibility);
071         string(a.beanMethodVisibility()).map(Visibility::valueOf).ifPresent(b::beanMethodVisibility);
072         bool(a.beanMapPutReturnsOldValue()).ifPresent(b::beanMapPutReturnsOldValue);
073         bool(a.beansRequireDefaultConstructor()).ifPresent(b::beansRequireDefaultConstructor);
074         bool(a.beansRequireSerializable()).ifPresent(b::beansRequireSerializable);
075         bool(a.beansRequireSettersForGetters()).ifPresent(b::beansRequireSettersForGetters);
076         bool(a.disableBeansRequireSomeProperties()).ifPresent(b::disableBeansRequireSomeProperties);
077         bool(a.findFluentSetters()).ifPresent(b::findFluentSetters);
078         bool(a.ignoreInvocationExceptionsOnGetters()).ifPresent(b::ignoreInvocationExceptionsOnGetters);
079         bool(a.ignoreInvocationExceptionsOnSetters()).ifPresent(b::ignoreInvocationExceptionsOnSetters);
080         bool(a.disableIgnoreMissingSetters()).ifPresent(b::disableIgnoreMissingSetters);
081         bool(a.disableIgnoreTransientFields()).ifPresent(b::disableIgnoreTransientFields);
082         bool(a.ignoreUnknownBeanProperties()).ifPresent(b::ignoreUnknownBeanProperties);
083         bool(a.validateSchema()).ifPresent(b::validateSchema);
084         bool(a.ignoreUnknownEnumValues()).ifPresent(b::ignoreUnknownEnumValues);
085         bool(a.disableIgnoreUnknownNullBeanProperties()).ifPresent(b::disableIgnoreUnknownNullBeanProperties);
086         bool(a.unsortedProperties()).ifPresent(b::unsortedProperties);
087         bool(a.recordComponentOrder()).ifPresent(b::recordComponentOrder);
088         bool(a.disableInterfaceProxies()).ifPresent(b::disableInterfaceProxies);
089         bool(a.useJavaBeanIntrospector()).ifPresent(b::useJavaBeanIntrospector);
090         classes(a.notBeanClasses()).ifPresent(b::notBeanClasses);
091         classes(a.notBeanClasses_replace()).ifPresent(x -> { b.notBeanClasses().clear(); b.notBeanClasses(x);});
092         type(a.propertyNamer()).ifPresent(b::propertyNamer);
093         l(a.interfaces()).stream().map(x -> BeanTypeApplyAnnotation.create(x).value(BeanTypeAnnotation.create().interfaceClass(x).build()).build()).forEach(b::annotations);
094         strings(a.notBeanPackages()).ifPresent(b::notBeanPackages);
095         strings(a.notBeanPackages_replace()).ifPresent(x -> {b.notBeanPackages().clear(); b.notBeanPackages(x);});
096         // @formatter:on
097      }
098   }
099}