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.html.panel; 018 019import org.apache.wicket.Component; 020import org.apache.wicket.markup.ComponentTag; 021import org.apache.wicket.markup.MarkupException; 022import org.apache.wicket.markup.MarkupStream; 023 024/** 025 * The Panel components markup sourcing strategy. 026 * <p> 027 * The strategy supports two modes on how to handle the body markup. A typical Panel will ignore the 028 * body markup and replace it with the associated markup. The body markup is allowed to have raw 029 * markup only and no Wicket components. But e.g. a Border component will associate the body markup 030 * with a Body component which renders the markup including all any number of child Components. 031 * 032 * @author Juergen Donnerstag 033 */ 034public class PanelMarkupSourcingStrategy extends AssociatedMarkupSourcingStrategy 035{ 036 private static final PanelMarkupSourcingStrategy PANEL_INSTANCE = new PanelMarkupSourcingStrategy( 037 false); 038 private static final PanelMarkupSourcingStrategy BORDER_INSTANCE = new PanelMarkupSourcingStrategy( 039 true); 040 041 // False for Panel and true for Border components. 042 private final boolean allowWicketComponentsInBodyMarkup; 043 044 /** 045 * @param allowWicketComponentsInBodyMarkup 046 * {@code false} for Panel and {@code true} for Border components. If Panel then the 047 * body markup should only contain raw markup, which is ignored (removed), but no 048 * Wicket Component. With Border components, the body markup will be associated with 049 * the Body Component. 050 * 051 * @return A singleton of the strategy 052 */ 053 public static PanelMarkupSourcingStrategy get(final boolean allowWicketComponentsInBodyMarkup) 054 { 055 return allowWicketComponentsInBodyMarkup ? BORDER_INSTANCE : PANEL_INSTANCE; 056 } 057 058 /** 059 * Constructor. 060 * 061 * @param wicketTagName 062 * The tag name for <code><wicket:'name' ..></code>. Please note that any such 063 * tag must have been registered via 064 * <code>WicketTagIdentifier.registerWellKnownTagName("name");</code> 065 * @param allowWicketComponentsInBodyMarkup 066 * {@code false} for Panel and {@code true} for Border components. If Panel then the 067 * body markup should only contain raw markup, which is ignored (removed), but no 068 * Wicket Component. With Border components, the body markup will be associated with 069 * the Body Component. 070 */ 071 public PanelMarkupSourcingStrategy(final String wicketTagName, 072 final boolean allowWicketComponentsInBodyMarkup) 073 { 074 super(wicketTagName); 075 076 this.allowWicketComponentsInBodyMarkup = allowWicketComponentsInBodyMarkup; 077 } 078 079 /** 080 * Constructor. 081 * 082 * @param allowWicketComponentsInBodyMarkup 083 * {@code false} for Panel and {@code true} for Border components. If Panel then the 084 * body markup should only contain raw markup, which is ignored (removed), but no 085 * Wicket Component. With Border components, the body markup will be associated with 086 * the Body Component. 087 */ 088 public PanelMarkupSourcingStrategy(final boolean allowWicketComponentsInBodyMarkup) 089 { 090 this(Panel.PANEL, allowWicketComponentsInBodyMarkup); 091 } 092 093 /** 094 * Skip the panel's body markup which is expected to contain raw markup only (no wicket 095 * components) and which will be ignored / removed. It'll be replaced with the content of the 096 * associated markup file. 097 */ 098 @Override 099 public void onComponentTagBody(final Component component, final MarkupStream markupStream, 100 final ComponentTag openTag) 101 { 102 if (allowWicketComponentsInBodyMarkup) 103 { 104 // Skip the body markup. Will be picked up by the Body component. 105 markupStream.skipToMatchingCloseTag(openTag); 106 } 107 else 108 { 109 // Skip the components body. Like with Panels or Fragments, it'll be replaced with the 110 // associated markup 111 if (markupStream.getPreviousTag().isOpen()) 112 { 113 markupStream.skipRawMarkup(); 114 if (markupStream.get().closes(openTag) == false) 115 { 116 StringBuilder msg = new StringBuilder(); 117 118 msg.append("Close tag not found for tag: ") 119 .append(openTag.toString()) 120 .append(". For ") 121 .append(component.getClass().getSimpleName()) 122 .append(" Components only raw markup is allow in between the tags but not ") 123 .append("other Wicket Component. Component: ") 124 .append(component.toString()); 125 126 throw new MarkupException(markupStream, msg.toString()); 127 } 128 } 129 } 130 131 renderAssociatedMarkup(component); 132 } 133}