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        }
076    
077        public String getTemplateDataAsString()
078        {
079            return new String(_templateData, _offset, _length);
080        }
081    
082        public int getLength()
083        {
084            return _length;
085        }
086    
087        public int getOffset()
088        {
089            return _offset;
090        }
091    }