/* * Hibernate Search, full-text search for your domain model * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.search.bridge.util.impl; import org.hibernate.search.bridge.ContainerBridge; import org.hibernate.search.bridge.TwoWayStringBridge; import org.hibernate.search.bridge.spi.IgnoreAnalyzerBridge; /** * Utilities allowing to take into account bridge adaptors when detecting implemented tagging * interface (e.g. {@link IgnoreAnalyzerBridge}) or when trying to make use of specific field * interfaces (e.g. {@link TwoWayStringBridge}). * * @author Yoann Rodiere */ public final class BridgeAdaptorUtils { private BridgeAdaptorUtils() { // private constructor } /** * Return a bridge of the specified type extracted from the given bridge, * going through {@link BridgeAdaptor adaptors} and {@link ContainerBridge container bridges} * as necessary. * * <p>The returned object may be the adaptor itself, or its delegate, or a delegate of * its delegate, and so on, but it may also be a element bridge of the given bridge if the * given bridge is a {@link ContainerBridge}, or an element bridge of a delegate of the given * bridge, and so on. * <p>If neither the adaptor nor one of its delegates can provide an instance of the * specified type, {@code null} is returned. * * @param bridge The bridge to use as a starting point. * @param clazz The expected bridge type. * @return A unwrapped bridge implementing the expected bridge type, or {@code null} * if none could be found. */ public static <T> T unwrapAdaptorAndContainer(Object bridge, Class<T> clazz) { T resultFromAdaptor = unwrapAdaptorOnly( bridge, clazz ); if ( resultFromAdaptor != null ) { return resultFromAdaptor; } Object elementBridge = getElementBridge( bridge ); if ( elementBridge != null ) { return unwrapAdaptorAndContainer( elementBridge, clazz ); } return null; } /** * Return the element bridge for the given bridge, if any, taking adaptors into account. * * <p>The returned object may be the element bridge for the given bridge itself, or its delegate, * or a delegate of its delegate, and so on. * <p>If neither the given bridge nor one of its delegates is a {@link ContainerBridge}, * {@code null} is returned. * * @param bridge The bridge to use as a starting point. * @param clazz The expected bridge type. * @return A unwrapped bridge implementing the expected bridge type, or {@code null} * if none could be found. */ private static Object getElementBridge(Object bridge) { ContainerBridge containerBridge = null; if ( bridge instanceof BridgeAdaptor ) { containerBridge = ( (BridgeAdaptor) bridge ).unwrap( ContainerBridge.class ); } else if ( bridge instanceof ContainerBridge ) { containerBridge = (ContainerBridge) bridge; } return containerBridge == null ? null : containerBridge.getElementBridge(); } /** * Return a bridge of the specified type extracted from the given bridge, * going through {@link BridgeAdaptor adaptors} as necessary, never going * through {@link ContainerBridge container bridges}. * * <p>The returned object may be the adaptor itself, or its delegate, or a delegate of * its delegate, and so on. * <p>If neither the adaptor or one of its delegates is an instance of the specified type, * {@code null} is returned. * * @param bridge The bridge to use as a starting point. * @param clazz The expected bridge type. * @return A unwrapped bridge implementing the expected bridge type, or {@code null} * if none could be found. */ public static <T> T unwrapAdaptorOnly(Object bridge, Class<T> clazz) { if ( clazz.isInstance( bridge ) ) { return clazz.cast( bridge ); } else if ( bridge instanceof BridgeAdaptor ) { return ( (BridgeAdaptor) bridge ).unwrap( clazz ); } else { return null; } } }