001//  Copyright 2008, 2009, 2010 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
015package org.apache.tapestry5.dom;
016
017public abstract class AbstractMarkupModel implements MarkupModel
018{
019    private final boolean useApostropheForAttributes;
020
021    protected AbstractMarkupModel(boolean useApostropheForAttributes)
022    {
023        this.useApostropheForAttributes = useApostropheForAttributes;
024    }
025
026    public char getAttributeQuote()
027    {
028        return useApostropheForAttributes ? '\'' : '"';
029    }
030
031    /**
032     * Passes all characters but '<', '>' and '&' through unchanged.
033     */
034    public String encode(String content)
035    {
036        int length = content.length();
037
038        StringBuilder builder = null;
039
040        for (int i = 0; i < length; i++)
041        {
042            char ch = content.charAt(i);
043
044            switch (ch)
045            {
046                case '<':
047
048                    if (builder == null)
049                    {
050                        builder = new StringBuilder(2 * length);
051
052                        builder.append(content.substring(0, i));
053                    }
054
055                    builder.append("&lt;");
056                    continue;
057
058                case '>':
059
060                    if (builder == null)
061                    {
062                        builder = new StringBuilder(2 * length);
063
064                        builder.append(content.substring(0, i));
065                    }
066
067                    builder.append("&gt;");
068                    continue;
069
070                case '&':
071
072                    if (builder == null)
073                    {
074                        builder = new StringBuilder(2 * length);
075
076                        builder.append(content.substring(0, i));
077                    }
078
079                    builder.append("&amp;");
080                    continue;
081
082                default:
083
084                    if (builder != null)
085                        builder.append(ch);
086            }
087        }
088
089        return builder == null ? content : builder.toString();
090    }
091
092    public void encodeQuoted(String content, StringBuilder builder)
093    {
094        assert content != null;
095        int length = content.length();
096
097        for (int i = 0; i < length; i++)
098        {
099            char ch = content.charAt(i);
100
101            switch (ch)
102            {
103                case '<':
104
105                    builder.append("&lt;");
106                    continue;
107
108                case '>':
109
110                    builder.append("&gt;");
111                    continue;
112
113                case '&':
114
115                    builder.append("&amp;");
116                    continue;
117
118                case '"':
119
120                    if (!useApostropheForAttributes)
121                    {
122                        builder.append("&quot;");
123                        continue;
124                    }
125
126                    builder.append(ch);
127                    continue;
128
129                case '\'':
130
131                    if (useApostropheForAttributes)
132                    {
133                        //TAP5-714
134                        builder.append("&#39;");
135                        continue;
136                    }
137
138
139                    // Fall through
140
141                default:
142
143                    builder.append(ch);
144            }
145        }
146    }
147}