001/* 002 * Shredzone Commons 003 * 004 * Copyright (C) 2012 Richard "Shred" Körber 005 * http://commons.shredzone.org 006 * 007 * This program is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU Library General Public License as 009 * published by the Free Software Foundation, either version 3 of the 010 * License, or (at your option) any later version. 011 * 012 * This program is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU Library General Public License 018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 019 */ 020package org.shredzone.commons.taglib; 021 022import javax.annotation.ParametersAreNonnullByDefault; 023import javax.servlet.jsp.tagext.Tag; 024import javax.servlet.jsp.tagext.TagSupport; 025 026import org.shredzone.commons.taglib.proxy.ProxiedTag; 027 028/** 029 * Utility class for taglib beans. 030 * 031 * @author Richard "Shred" Körber 032 */ 033@ParametersAreNonnullByDefault 034public final class TaglibUtils { 035 036 private TaglibUtils() {} 037 038 /** 039 * Finds an ancestor tag of the given type. Starting from the given Tag, it traverses 040 * up the parent tags until a tag of the given type is found. 041 * <p> 042 * Use this method instead of {@link TagSupport#findAncestorWithClass(Tag, Class)}, as 043 * it is aware of proxied tag classes, while findAncestorWithClass only sees the 044 * proxy instances instead of the tag classes behind it. Furthermore, this method is 045 * also able to locate interfaces. 046 * 047 * @param <T> 048 * Type to find and return 049 * @param from 050 * Tag to start from 051 * @param type 052 * Type to find 053 * @return Ancestor of that type, or {@code null} if none was found. 054 */ 055 @SuppressWarnings("unchecked") 056 public static <T> T findAncestorWithType(Tag from, Class<T> type) { 057 Tag parent = from.getParent(); 058 while (parent != null) { 059 if (parent instanceof ProxiedTag) { 060 parent = ((ProxiedTag<Tag>) parent).getTargetBean(); 061 } 062 if (type.isAssignableFrom(parent.getClass())) { 063 return (T) parent; 064 } 065 parent = parent.getParent(); 066 } 067 return null; 068 } 069 070}