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: */
017: package org.apache.wicket.markup.loader;
018:
019: import java.io.IOException;
020:
021: import org.apache.wicket.Application;
022: import org.apache.wicket.MarkupContainer;
023: import org.apache.wicket.markup.Markup;
024: import org.apache.wicket.markup.MarkupElement;
025: import org.apache.wicket.markup.MarkupNotFoundException;
026: import org.apache.wicket.markup.MarkupResourceStream;
027: import org.apache.wicket.markup.MergedMarkup;
028: import org.apache.wicket.markup.WicketTag;
029: import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
030: import org.slf4j.Logger;
031: import org.slf4j.LoggerFactory;
032:
033: /**
034: * Merge the 2+ markups involved in markup inheritance. From a users perspective
035: * there is only one markup associated with the component, the merged one.
036: *
037: * @author Juergen Donnerstag
038: */
039: public class InheritedMarkupMarkupLoader implements IMarkupLoader {
040: /** Log for reporting. */
041: private static final Logger log = LoggerFactory
042: .getLogger(InheritedMarkupMarkupLoader.class);
043:
044: /**
045: * Constructor.
046: *
047: * @param cache
048: */
049: public InheritedMarkupMarkupLoader() {
050: }
051:
052: /**
053: *
054: * @see org.apache.wicket.markup.loader.IMarkupLoader#loadMarkup(org.apache.wicket.MarkupContainer,
055: * org.apache.wicket.markup.MarkupResourceStream,
056: * org.apache.wicket.markup.loader.IMarkupLoader, boolean)
057: */
058: public final Markup loadMarkup(final MarkupContainer container,
059: final MarkupResourceStream markupResourceStream,
060: final IMarkupLoader baseLoader, final boolean enforceReload)
061: throws IOException, ResourceStreamNotFoundException {
062: // read and parse the markup
063: Markup markup = baseLoader.loadMarkup(container,
064: markupResourceStream, null, enforceReload);
065: markup = checkForMarkupInheritance(container, markup,
066: enforceReload);
067: return markup;
068: }
069:
070: /**
071: * The markup has just been loaded and now we check if markup inheritance
072: * applies, which is if <wicket:extend> is found in the markup. If yes, than
073: * load the base markups and merge the markup elements to create an updated
074: * (merged) list of markup elements.
075: *
076: * @param container
077: * The original requesting markup container
078: * @param markup
079: * The markup to checked for inheritance
080: * @param enforceReload
081: * The cache will be ignored and all, including inherited markup
082: * files, will be reloaded. Whatever is in the cache, it will be
083: * ignored
084: * @return A markup object with the the base markup elements resolved.
085: * @TODO move into IMarkupLoader
086: */
087: private Markup checkForMarkupInheritance(
088: final MarkupContainer container, final Markup markup,
089: final boolean enforceReload) {
090: // Check if markup contains <wicket:extend> which tells us that
091: // we need to read the inherited markup as well.
092: int extendIndex = requiresBaseMarkup(markup);
093: if (extendIndex == -1) {
094: // return a MarkupStream for the markup
095: return markup;
096: }
097:
098: // get the base markup
099: final Markup baseMarkup = Application.get().getMarkupSettings()
100: .getMarkupCache().getMarkup(
101: container,
102: markup.getMarkupResourceData().getResource()
103: .getMarkupClass().getSuperclass(),
104: enforceReload);
105:
106: if (baseMarkup == Markup.NO_MARKUP) {
107: throw new MarkupNotFoundException(
108: "Base markup of inherited markup not found. Component class: "
109: + markup.getMarkupResourceData()
110: .getResource().getContainerInfo()
111: .getContainerClass().getName()
112: + " Enable debug messages for org.apache.wicket.util.resource.Resource to get a list of all filenames tried.");
113: }
114:
115: // Merge base and derived markup
116: return new MergedMarkup(markup, baseMarkup, extendIndex);
117: }
118:
119: /**
120: * Check if markup contains <wicket:extend> which tells us that we
121: * need to read the inherited markup as well. <wicket:extend> MUST BE
122: * the first wicket tag in the markup. Skip raw markup
123: *
124: * @param markup
125: * @return == 0, if no wicket:extend was found
126: * @TODO move into IMarkupLoader
127: */
128: private int requiresBaseMarkup(final Markup markup) {
129: for (int i = 0; i < markup.size(); i++) {
130: MarkupElement elem = markup.get(i);
131: if (elem instanceof WicketTag) {
132: WicketTag wtag = (WicketTag) elem;
133: if (wtag.isExtendTag()) {
134: // Ok, inheritance is on and we must get the
135: // inherited markup as well.
136: return i;
137: }
138: }
139: }
140: return -1;
141: }
142: }
|