001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.parse;
016    
017    import org.apache.hivemind.ApplicationRuntimeException;
018    import org.apache.hivemind.Location;
019    import org.apache.hivemind.util.ToStringBuilder;
020    import org.apache.tapestry.IMarkupWriter;
021    import org.apache.tapestry.IRender;
022    import org.apache.tapestry.IRequestCycle;
023    
024    /**
025     * Represents static text in the template that may be passed through to the client unchanged
026     * (except, perhaps, for the removal of some whitespace).
027     * 
028     * @see TokenType#TEXT
029     * @author Howard Lewis Ship
030     * @since 3.0
031     */
032    
033    public class TextToken extends TemplateToken implements IRender
034    {
035        private char[] _templateData;
036    
037        private int _offset;
038    
039        private int _length;
040    
041        public TextToken(char[] templateData, int startIndex, int endIndex, Location location)
042        {
043            super(TokenType.TEXT, location);
044    
045            if (startIndex < 0 || endIndex < 0 || startIndex > templateData.length
046                    || endIndex > templateData.length)
047                throw new ApplicationRuntimeException(ParseMessages.rangeError(
048                        this,
049                        templateData.length), this, getLocation(), null);
050    
051            _templateData = templateData;
052    
053            _offset = startIndex;
054            _length = endIndex - startIndex + 1;
055        }
056    
057        public void render(IMarkupWriter writer, IRequestCycle cycle)
058        {
059            if (_length == 0)
060                return;
061    
062            // At one time, we would check to see if the cycle was rewinding and
063            // only invoke printRaw() if it was. However, that slows down
064            // normal rendering (microscopically) and, with the new
065            // NullResponseWriter class, the "cost" of invoking cycle.isRewinding()
066            // is approximately the same as the "cost" of invoking writer.printRaw().
067    
068            writer.printRaw(_templateData, _offset, _length);
069        }
070    
071        protected void extendDescription(ToStringBuilder builder)
072        {
073            builder.append("offset", _offset);
074            builder.append("length", _length);
075            builder.append("templateData", getTemplateDataAsString());
076        }
077    
078        public String getTemplateDataAsString()
079        {
080            return new String(_templateData, _offset, _length);
081        }
082    
083        public int getLength()
084        {
085            return _length;
086        }
087    
088        public int getOffset()
089        {
090            return _offset;
091        }
092    }