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

org.apache.juneau.swap.AutoObjectSwap 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.swap;

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

import java.lang.reflect.*;
import java.util.*;

import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.reflect.*;
import org.apache.juneau.serializer.*;

/**
 * A dynamic object swap based on reflection of a Java class that converts Objects to serializable objects.
 *
 * 

* Looks for methods on the class that can be called to swap-in surrogate objects before serialization and swap-out * surrogate objects after parsing. * *

Valid surrogate objects
*
    *
  • {@link String} *
  • {@link Number} *
  • {@link Boolean} *
  • {@link Map} *
  • {@link Collection} *
* *
Valid swap methods (S = Swapped type)
*
    *
  • public S swap() *
  • public S swap(BeanSession) *
  • public S toObject() *
  • public S toObject(BeanSession) *
* *
Valid unswap methods (N = Normal type, S = Swapped type)
*
    *
  • public static N unswap(S) *
  • public static N unswap(BeanSession, S) *
  • public static N fromObject(S) *
  • public static N fromObject(BeanSession, S) *
  • public static N create(S) *
  • public static N create(BeanSession, S) *
  • public N(S) *
* *

* Classes are ignored if any of the following are true: *

    *
  • Classes annotated with {@link BeanIgnore @BeanIgnore}. *
  • Non-static member classes. *
* *

* Members/constructors are ignored if any of the following are true: *

    *
  • Members/constructors annotated with {@link BeanIgnore @BeanIgnore}. *
  • Deprecated members/constructors. *
* *
See Also:
* * @param The normal class type. */ public class AutoObjectSwap extends ObjectSwap { private static final Set SWAP_METHOD_NAMES = uset("swap", "toObject"), UNSWAP_METHOD_NAMES = uset("unswap", "create", "fromObject", "of"); /** * Inspects the specified class and returns a swap of this type if possible. * * @param bc The bean context to use for looking up annotations. * @param ci The class to return a swap on. * @return An object swap instance, or null if one could not be created. */ @SuppressWarnings({ "rawtypes" }) public static ObjectSwap find(BeanContext bc, ClassInfo ci) { if (shouldIgnore(bc, ci)) return null; // Find swap() method if present. for (MethodInfo m : ci.getMethods()) { if (isSwapMethod(bc, m)) { ClassInfo rt = m.getReturnType(); MethodInfo mi = ci.getMethod(x -> isUnswapMethod(bc, x, ci, rt)); if (mi != null) return new AutoObjectSwap(bc, ci, m, mi, null); ConstructorInfo cs = ci.getDeclaredConstructor(x -> isUnswapConstructor(bc, x, rt)); if (cs != null) return new AutoObjectSwap(bc, ci, m, null, cs); return new AutoObjectSwap(bc, ci, m, null, null); } } return null; } private static boolean shouldIgnore(BeanContext bc, ClassInfo ci) { return ci.hasAnnotation(bc, BeanIgnore.class) || ci.isNonStaticMemberClass(); } private static boolean isSwapMethod(BeanContext bc, MethodInfo mi) { return mi.isNotDeprecated() && mi.isNotStatic() && mi.isVisible(bc.getBeanMethodVisibility()) && mi.hasName(SWAP_METHOD_NAMES) && mi.hasFuzzyParamTypes(BeanSession.class) && mi.hasNoAnnotation(bc, BeanIgnore.class); } private static boolean isUnswapMethod(BeanContext bc, MethodInfo mi, ClassInfo ci, ClassInfo rt) { return mi.isNotDeprecated() && mi.isStatic() && mi.isVisible(bc.getBeanMethodVisibility()) && mi.hasName(UNSWAP_METHOD_NAMES) && mi.hasFuzzyParamTypes(BeanSession.class, rt.inner()) && mi.hasReturnTypeParent(ci) && mi.hasNoAnnotation(bc, BeanIgnore.class); } private static boolean isUnswapConstructor(BeanContext bc, ConstructorInfo cs, ClassInfo rt) { return cs.isNotDeprecated() && cs.isVisible(bc.getBeanConstructorVisibility()) && cs.hasMatchingParamTypes(rt) && cs.hasNoAnnotation(bc, BeanIgnore.class); } //------------------------------------------------------------------------------------------------------------------ private final Method swapMethod, unswapMethod; private final Constructor unswapConstructor; private AutoObjectSwap(BeanContext bc, ClassInfo ci, MethodInfo swapMethod, MethodInfo unswapMethod, ConstructorInfo unswapConstructor) { super(ci.inner(), swapMethod.inner().getReturnType()); this.swapMethod = bc.getBeanMethodVisibility().transform(swapMethod.inner()); this.unswapMethod = unswapMethod == null ? null : bc.getBeanMethodVisibility().transform(unswapMethod.inner()); this.unswapConstructor = unswapConstructor == null ? null : bc.getBeanConstructorVisibility().transform(unswapConstructor.inner()); } @Override /* ObjectSwap */ public Object swap(BeanSession session, Object o) throws SerializeException { try { return swapMethod.invoke(o, getMatchingArgs(swapMethod.getParameterTypes(), session)); } catch (Exception e) { throw SerializeException.create(e); } } @SuppressWarnings("unchecked") @Override /* ObjectSwap */ public T unswap(BeanSession session, Object f, ClassMeta hint) throws ParseException { try { if (unswapMethod != null) return (T)unswapMethod.invoke(null, getMatchingArgs(unswapMethod.getParameterTypes(), session, f)); if (unswapConstructor != null) return (T)unswapConstructor.newInstance(f); return super.unswap(session, f, hint); } catch (Exception e) { throw ParseException.create(e); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy