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.parser.filter;
018
019import java.text.ParseException;
020import java.util.Map;
021import java.util.concurrent.atomic.AtomicInteger;
022
023import org.apache.wicket.markup.ComponentTag;
024import org.apache.wicket.markup.HtmlSpecialTag;
025import org.apache.wicket.markup.Markup;
026import org.apache.wicket.markup.MarkupElement;
027import org.apache.wicket.markup.MarkupResourceStream;
028import org.apache.wicket.markup.parser.AbstractMarkupFilter;
029import org.apache.wicket.markup.parser.IMarkupFilter;
030import org.apache.wicket.markup.parser.IXmlPullParser;
031import org.apache.wicket.markup.parser.IXmlPullParser.HttpTagType;
032import org.apache.wicket.request.cycle.RequestCycle;
033
034
035/**
036 * This is the root of all filters, which retrieves the next xml element from the xml parser.
037 * 
038 * @author Juergen Donnerstag
039 */
040public final class RootMarkupFilter extends AbstractMarkupFilter
041{
042        /** The xml parser */
043        private final IXmlPullParser parser;
044
045        /**
046         * Construct.
047         * 
048         * @param parser
049         */
050        public RootMarkupFilter(final IXmlPullParser parser, MarkupResourceStream resourceStream)
051        {
052                super(resourceStream);
053                this.parser = parser;
054        }
055
056        /**
057         * Skip all xml elements until the next tag.
058         */
059        @Override
060        public final MarkupElement nextElement() throws ParseException
061        {
062                HttpTagType type;
063                while ((type = parser.next()) != HttpTagType.NOT_INITIALIZED)
064                {
065                        if (type == HttpTagType.BODY)
066                        {
067                                continue;
068                        }
069                        else if (type == HttpTagType.TAG)
070                        {
071                                return new ComponentTag(parser.getElement());
072                        }
073                        else
074                        {
075                                return new HtmlSpecialTag(parser.getElement(), type);
076                        }
077                }
078
079                return null;
080        }
081
082        /**
083         * @return null. This is the root filter.
084         */
085        @Override
086        public final IMarkupFilter getNextFilter()
087        {
088                return null;
089        }
090
091        /**
092         * This is the root filter. Operation not allowed. An exception will be thrown.
093         */
094        @Override
095        public final void setNextFilter(final IMarkupFilter parent)
096        {
097                throw new IllegalArgumentException("You can not set the parent with RootMarkupFilter.");
098        }
099
100        /**
101         * Noop
102         */
103        @Override
104        protected MarkupElement onComponentTag(ComponentTag tag) throws ParseException
105        {
106                return tag;
107        }
108
109        /**
110         * Noop
111         */
112        @Override
113        public final void postProcess(Markup markup)
114        {
115                //once we have done filtering, we reset markup counters for ids 
116                RequestCycle requestCycle = RequestCycle.get();
117                Map<String, AtomicInteger> markupUniqueCounters = requestCycle.getMetaData(REQUEST_COUNTER_KEY);
118                
119                if (markupUniqueCounters != null)
120                {                       
121                        markupUniqueCounters.clear();
122                }
123        }
124
125        /**
126         * @see java.lang.Object#toString()
127         */
128        @Override
129        public String toString()
130        {
131                return parser.toString();
132        }
133}