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; 018 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.Collections; 022import java.util.Iterator; 023import java.util.List; 024 025import org.apache.wicket.util.lang.Args; 026import org.apache.wicket.util.resource.ResourceStreamNotFoundException; 027import org.apache.wicket.util.string.AppendingStringBuffer; 028 029 030/** 031 * The content of a markup file, consisting of a list of markup elements. 032 * 033 * @see MarkupResourceStream 034 * @see MarkupElement 035 * @see ComponentTag 036 * @see RawMarkup 037 * 038 * @author Juergen Donnerstag 039 */ 040public class Markup extends AbstractMarkupFragment 041{ 042 /** Placeholder that indicates no markup */ 043 public static final Markup NO_MARKUP = new Markup(); 044 045 /** The list of markup elements */ 046 private/* final */List<MarkupElement> markupElements; 047 048 /** The associated markup file */ 049 private final MarkupResourceStream markupResourceStream; 050 051 /** 052 * Take the markup string, parse it and return the Markup (list of MarkupElements). 053 * <p> 054 * Limitation: Please note that MarkupFactory is NOT used and thus no caching is used (which 055 * doesn't matter for Strings anyway), but what might matter is that your own MarkupFilters are 056 * not applied, which you might have registered with MarkupFactory. 057 * 058 * @param markup 059 * the string to use as markup 060 * @return Markup The parsed markup 061 */ 062 public static Markup of(final String markup) 063 { 064 return of(markup, MarkupParser.WICKET); 065 } 066 067 /** 068 * Take the markup string, parse it and return the Markup (list of MarkupElements). 069 * <p> 070 * Limitation: Please note that MarkupFactory is NOT used and thus no caching is used (which 071 * doesn't matter for Strings anyway), but what might matter is that your own MarkupFilters are 072 * not applied, which you might have registered with MarkupFactory. 073 * 074 * @param markup 075 * the string to use as markup 076 * @param wicketNamespace 077 * the namespace for Wicket elements and attributes 078 * @return Markup The parsed markup 079 */ 080 public static Markup of(final String markup, String wicketNamespace) 081 { 082 try 083 { 084 MarkupParser markupParser = new MarkupParser(markup); 085 markupParser.setWicketNamespace(wicketNamespace); 086 return markupParser.parse(); 087 } 088 catch (IOException ex) 089 { 090 throw new RuntimeException(ex); 091 } 092 catch (ResourceStreamNotFoundException ex) 093 { 094 throw new RuntimeException(ex); 095 } 096 } 097 098 /** 099 * Private Constructor for NO_MARKUP only 100 */ 101 private Markup() 102 { 103 markupResourceStream = null; 104 } 105 106 /** 107 * Constructor 108 * 109 * @param markupResourceStream 110 * The associated Markup 111 */ 112 public Markup(final MarkupResourceStream markupResourceStream) 113 { 114 Args.notNull(markupResourceStream, "markupResourceStream"); 115 116 this.markupResourceStream = markupResourceStream; 117 markupElements = new ArrayList<>(); 118 } 119 120 @Override 121 public final MarkupElement get(final int index) 122 { 123 return markupElements.get(index); 124 } 125 126 @Override 127 public final MarkupResourceStream getMarkupResourceStream() 128 { 129 return markupResourceStream; 130 } 131 132 /** 133 * 134 * @param index 135 * @param elem 136 */ 137 public final void replace(final int index, final MarkupElement elem) 138 { 139 Args.notNull(elem, "elem"); 140 141 if ((index < 0) || (index >= size())) 142 { 143 throw new IndexOutOfBoundsException("'index' must be smaller than size(). Index:" + 144 index + "; size:" + size()); 145 } 146 147 markupElements.set(index, elem); 148 } 149 150 /** 151 * 152 * @return The fixed location as a string, e.g. the file name or the URL. Return null to avoid 153 * caching the markup. 154 */ 155 public String locationAsString() 156 { 157 return markupResourceStream.locationAsString(); 158 } 159 160 @Override 161 public final int size() 162 { 163 return markupElements.size(); 164 } 165 166 /** 167 * Add a MarkupElement 168 * 169 * @param markupElement 170 */ 171 final public void addMarkupElement(final MarkupElement markupElement) 172 { 173 markupElements.add(markupElement); 174 } 175 176 /** 177 * Add a MarkupElement 178 * 179 * @param pos 180 * @param markupElement 181 */ 182 final public void addMarkupElement(final int pos, final MarkupElement markupElement) 183 { 184 markupElements.add(pos, markupElement); 185 } 186 187 /** 188 * Make all tags immutable and the list of elements unmodifiable. 189 */ 190 final public void makeImmutable() 191 { 192 for (MarkupElement markupElement : markupElements) 193 { 194 if (markupElement instanceof ComponentTag) 195 { 196 // Make the tag immutable 197 ((ComponentTag)markupElement).makeImmutable(); 198 } 199 } 200 201 markupElements = Collections.unmodifiableList(markupElements); 202 } 203 204 @Override 205 public final IMarkupFragment find(final String id) 206 { 207 return find(id, 0); 208 } 209 210 @Override 211 public final String toString() 212 { 213 return toString(false); 214 } 215 216 /** 217 * @param markupOnly 218 * True, if only the markup shall be returned 219 * @return String 220 */ 221 @Override 222 public final String toString(final boolean markupOnly) 223 { 224 final AppendingStringBuffer buf = new AppendingStringBuffer(400); 225 226 if (markupOnly == false) 227 { 228 if (markupResourceStream != null) 229 { 230 buf.append(markupResourceStream.toString()); 231 } 232 else 233 { 234 buf.append("null MarkupResouceStream"); 235 } 236 buf.append("\n"); 237 } 238 239 if (markupElements != null) 240 { 241 for (MarkupElement markupElement : markupElements) 242 { 243 buf.append(markupElement); 244 } 245 } 246 247 return buf.toString(); 248 } 249 250 /** 251 * @see java.lang.Iterable#iterator() 252 */ 253 @Override 254 public final Iterator<MarkupElement> iterator() 255 { 256 return markupElements.iterator(); 257 } 258 259 /** 260 * @param startIndex 261 * @param size 262 * @return Iterator 263 */ 264 public final Iterator<MarkupElement> iterator(int startIndex, int size) 265 { 266 return markupElements.subList(startIndex, startIndex + size).iterator(); 267 } 268}