001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.servlet.taglib.aui;
016    
017    import com.liferay.portal.kernel.servlet.BrowserSnifferUtil;
018    import com.liferay.portal.kernel.util.Mergeable;
019    import com.liferay.portal.kernel.util.StringBundler;
020    import com.liferay.portal.kernel.util.StringPool;
021    import com.liferay.portal.kernel.util.StringUtil;
022    import com.liferay.portal.kernel.util.Validator;
023    
024    import java.io.IOException;
025    import java.io.Serializable;
026    import java.io.Writer;
027    
028    import java.util.HashMap;
029    import java.util.Map;
030    import java.util.Set;
031    import java.util.TreeSet;
032    import java.util.concurrent.ConcurrentHashMap;
033    import java.util.concurrent.ConcurrentMap;
034    
035    import javax.servlet.http.HttpServletRequest;
036    
037    /**
038     * @author Brian Wing Shun Chan
039     * @author Shuyang Zhou
040     */
041    public class ScriptData implements Mergeable<ScriptData>, Serializable {
042    
043            public void append(String portletId, String content, String use) {
044                    PortletData portletData = _getPortletData(portletId);
045    
046                    portletData.append(content, use);
047            }
048    
049            public void append(String portletId, StringBundler contentSB, String use) {
050                    PortletData portletData = _getPortletData(portletId);
051    
052                    portletData.append(contentSB, use);
053            }
054    
055            public void mark() {
056                    for (PortletData portletData : _portletDataMap.values()) {
057                            StringBundler callbackSB = portletData._callbackSB;
058    
059                            _sbIndexMap.put(callbackSB, callbackSB.index());
060    
061                            StringBundler rawSB = portletData._rawSB;
062    
063                            _sbIndexMap.put(rawSB, rawSB.index());
064                    }
065            }
066    
067            public ScriptData merge(ScriptData scriptData) {
068                    if ((scriptData != null) && (scriptData != this)) {
069                            _portletDataMap.putAll(scriptData._portletDataMap);
070                    }
071    
072                    return this;
073            }
074    
075            public void reset() {
076                    for (Map.Entry<StringBundler, Integer> entry : _sbIndexMap.entrySet()) {
077                            StringBundler sb = entry.getKey();
078    
079                            sb.setIndex(entry.getValue());
080                    }
081            }
082    
083            public void writeTo(HttpServletRequest request, Writer writer)
084                    throws IOException {
085    
086                    writer.write("<script type=\"text/javascript\">\n// <![CDATA[\n");
087    
088                    StringBundler callbackSB = new StringBundler();
089    
090                    for (PortletData portletData : _portletDataMap.values()) {
091                            portletData._rawSB.writeTo(writer);
092    
093                            callbackSB.append(portletData._callbackSB);
094                    }
095    
096                    if (callbackSB.index() > 0) {
097                            String loadMethod = "use";
098    
099                            if (BrowserSnifferUtil.isIe(request) &&
100                                    (BrowserSnifferUtil.getMajorVersion(request) < 8)) {
101    
102                                    loadMethod = "ready";
103                            }
104    
105                            writer.write("AUI().");
106                            writer.write(loadMethod);
107                            writer.write("(");
108    
109                            Set<String> useSet = new TreeSet<String>();
110    
111                            for (PortletData portletData : _portletDataMap.values()) {
112                                    useSet.addAll(portletData._useSet);
113                            }
114    
115                            for (String use : useSet) {
116                                    writer.write(StringPool.APOSTROPHE);
117                                    writer.write(use);
118                                    writer.write(StringPool.APOSTROPHE);
119                                    writer.write(StringPool.COMMA_AND_SPACE);
120                            }
121    
122                            writer.write("function(A) {");
123    
124                            callbackSB.writeTo(writer);
125    
126                            writer.write("});");
127                    }
128    
129                    writer.write("\n// ]]>\n</script>");
130            }
131    
132            private PortletData _getPortletData(String portletId) {
133                    if (Validator.isNull(portletId)) {
134                            portletId = StringPool.BLANK;
135                    }
136    
137                    PortletData portletData = _portletDataMap.get(portletId);
138    
139                    if (portletData == null) {
140                            portletData = new PortletData();
141    
142                            PortletData oldPortletData = _portletDataMap.putIfAbsent(
143                                    portletId, portletData);
144    
145                            if (oldPortletData != null) {
146                                    portletData = oldPortletData;
147                            }
148                    }
149    
150                    return portletData;
151            }
152    
153            private static final long serialVersionUID = 1L;
154    
155            private ConcurrentMap<String, PortletData> _portletDataMap =
156                    new ConcurrentHashMap<String, PortletData>();
157            private Map<StringBundler, Integer> _sbIndexMap =
158                    new HashMap<StringBundler, Integer>();
159    
160            private class PortletData implements Serializable {
161    
162                    public void append(String content, String use) {
163                            if (Validator.isNull(use)) {
164                                    _rawSB.append(content);
165                            }
166                            else {
167                                    _callbackSB.append("(function() {");
168                                    _callbackSB.append(content);
169                                    _callbackSB.append("})();");
170    
171                                    String[] useArray = StringUtil.split(use);
172    
173                                    for (int i = 0; i < useArray.length; i++) {
174                                            _useSet.add(useArray[i]);
175                                    }
176                            }
177                    }
178    
179                    public void append(StringBundler contentSB, String use) {
180                            if (Validator.isNull(use)) {
181                                    _rawSB.append(contentSB);
182                            }
183                            else {
184                                    _callbackSB.append("(function() {");
185                                    _callbackSB.append(contentSB);
186                                    _callbackSB.append("})();");
187    
188                                    String[] useArray = StringUtil.split(use);
189    
190                                    for (int i = 0; i < useArray.length; i++) {
191                                            _useSet.add(useArray[i]);
192                                    }
193                            }
194                    }
195    
196                    private static final long serialVersionUID = 1L;
197    
198                    private StringBundler _callbackSB = new StringBundler();
199                    private StringBundler _rawSB = new StringBundler();
200                    private Set<String> _useSet = new TreeSet<String>();
201    
202            }
203    
204    }