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.wicket.markup.resolver; 018 019import org.apache.wicket.Application; 020import org.apache.wicket.Component; 021import org.apache.wicket.MarkupContainer; 022import org.apache.wicket.markup.ComponentTag; 023import org.apache.wicket.markup.MarkupStream; 024 025/** 026 * Utility class for {@link IComponentResolver}s 027 * 028 * @author igor.vaynberg 029 */ 030public class ComponentResolvers 031{ 032 private ComponentResolvers() 033 { 034 } 035 036 /** 037 * Attempts to resolve a component using resolvers. Tries resolvers in the component hierarchy 038 * as well as application-wide. 039 * <p> 040 * This method encapsulates the contract of resolving components and should be used any time a 041 * component needs to be resolved under normal circumstances. 042 * </p> 043 * 044 * @param container 045 * The container parsing its markup 046 * @param markupStream 047 * The current markupStream 048 * @param tag 049 * The current component tag while parsing the markup 050 * @param filter 051 * A filter for application-wide resolvers 052 * @return component or {@code null} if not found 053 */ 054 public static Component resolve(final MarkupContainer container, 055 final MarkupStream markupStream, final ComponentTag tag, final ResolverFilter filter) 056 { 057 // try to resolve using component hierarchy 058 Component component = resolveByComponentHierarchy(container, markupStream, tag); 059 060 if (component == null) 061 { 062 // fallback to application-level resolvers 063 component = resolveByApplication(container, markupStream, tag, filter); 064 } 065 066 return component; 067 } 068 069 /** 070 * Attempts to resolve a component via application registered resolvers. 071 * 072 * @param container 073 * @param markupStream 074 * @param tag 075 * @param filter 076 * @return Null, if no component was found 077 */ 078 public static Component resolveByApplication(final MarkupContainer container, 079 final MarkupStream markupStream, final ComponentTag tag, final ResolverFilter filter) 080 { 081 for (final IComponentResolver resolver : Application.get() 082 .getPageSettings() 083 .getComponentResolvers()) 084 { 085 if ((filter == null) || (filter.ignoreResolver(resolver) == false)) 086 { 087 Component component = resolver.resolve(container, markupStream, tag); 088 if (component != null) 089 { 090 return component; 091 } 092 } 093 } 094 095 return null; 096 } 097 098 /** 099 * Attempts to resolve a component via the component hierarchy using resolvers. 100 * 101 * @param container 102 * @param markupStream 103 * @param tag 104 * @return Null, if no component was found 105 */ 106 public static Component resolveByComponentHierarchy(final MarkupContainer container, 107 final MarkupStream markupStream, final ComponentTag tag) 108 { 109 Component cursor = container; 110 while (cursor != null) 111 { 112 if (cursor instanceof IComponentResolver) 113 { 114 IComponentResolver resolver = (IComponentResolver)cursor; 115 Component component = resolver.resolve(container, markupStream, tag); 116 if (component != null) 117 { 118 return component; 119 } 120 } 121 cursor = cursor.getParent(); 122 } 123 124 return null; 125 } 126 127 public interface ResolverFilter 128 { 129 /** 130 * 131 * @param resolver 132 * @return true, if resolvers should be skipped 133 */ 134 boolean ignoreResolver(IComponentResolver resolver); 135 } 136}