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