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    
015    package org.apache.tapestry5.dom;
016    
017    public 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    }