001    /*
002     * Licensed under the Apache License, Version 2.0 (the "License");
003     * you may not use this file except in compliance with the License.
004     * You may obtain a copy of the License at
005     *
006     * http://www.apache.org/licenses/LICENSE-2.0
007     *
008     * Unless required by applicable law or agreed to in writing, software
009     * distributed under the License is distributed on an "AS IS" BASIS,
010     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011     * See the License for the specific language governing permissions and
012     * limitations under the License.
013     * 
014     * See the NOTICE file distributed with this work for additional
015     * information regarding copyright ownership.
016     */
017    
018    package com.osbcp.jjsw;
019    
020    import java.io.Serializable;
021    
022    /**
023     * JavaScript wrapper object.
024     *
025     * @author @author <a href=\"mailto:christoffer@christoffer.me\">Christoffer Pettersson</a>
026     */
027    
028    public class JavaScript implements Serializable {
029    
030            private static final long serialVersionUID = 1L;
031    
032            /**
033             * Different output types.
034             * 
035             * @author @author <a href=\"mailto:christoffer@christoffer.me\">Christoffer Pettersson</a>
036             */
037    
038            public enum TYPE {
039    
040                    /**
041                     * Downgrades all double quotation marks " into single quotation mark '.
042                     */
043    
044                    DOWNGRADE,
045    
046                    /**
047                     * Escapes all double quotation marks " into HTML character &amp;quot;.
048                     */
049    
050                    ESCAPED;
051    
052            }
053    
054            private String javaScriptObjectName;
055            private StringBuilder code;
056            private Object[] parameters;
057    
058            /**
059             * Creates an empty JavaScript code instance.
060             */
061    
062            public JavaScript() {
063                    this("");
064            }
065    
066            /**
067             * Creates a new JavaScript instance based on a specific code. 
068             * 
069             * @param code The JavaScript code as String that should be appended
070             */
071    
072            public JavaScript(final String code) {
073                    this("$jjsw", code);
074            }
075    
076            /**
077             * Creates a new JavaScript instance based on a specific code. Any additional parameters will be concatenated into the code via the %s annotation.
078             * For example:
079             * String name = "John"; 
080             * JavaScriptFunction function = new JavaScriptFunction("alert(\"%s\");", name ); 
081             * 
082             * @param javaScriptObjectName The JavaScript object name, for example "$test"
083             * @param code The JavaScript code
084             * @param parameters Any parameters that should be used in the JavaScript code. Each parameter should be declared as %s in the code. For example: alert('Hello %s %s!'); where the %s are parameters. 
085             */
086    
087            public JavaScript(final String javaScriptObjectName, final String code, final Object... parameters) {
088    
089                    // Validate the parameters
090                    Validator.validateJavaScriptArguments(javaScriptObjectName, code);
091    
092                    // Initialize the the variables
093                    this.javaScriptObjectName = javaScriptObjectName;
094                    this.code = new StringBuilder(code);
095                    this.parameters = parameters;
096    
097            }
098    
099            /**
100             * Appends a JavaScript code to the existing JavaScript code.
101             * 
102             * @param code The JavaScript code to be appended
103             */
104    
105            public void append(final JavaScript code) {
106                    append(code.toString());
107            }
108    
109            /**
110             * Appends a String to the JavaScript code.
111             * 
112             * @param code The code to be appended
113             */
114    
115            public void append(final String code) {
116                    this.code.append(code);
117            }
118    
119            /**
120             * Returns the JavaScript code as a String.
121             * 
122             * @return The JavaScript code as a String.
123             */
124    
125            public String toString() {
126    
127                    // Copy the code to a new variable
128                    String tempCode = code.toString();
129    
130                    // Inject the arguments
131                    tempCode = StringUtil.injectJavaScriptVariables(parameters, tempCode);
132    
133                    // Escape the JavaScript variables
134                    tempCode = StringUtil.escapeJavaScriptVaribles(tempCode, parameters.length);
135    
136                    // Return the injected and escaped code
137                    return tempCode;
138    
139            }
140    
141            /**
142             * Outputs the JavaScript based on a specific output type.
143             * 
144             * @param type Type of output
145             * @return JavaScript as a String
146             */
147    
148            public String toString(final TYPE type) {
149    
150                    switch (type) {
151                            case DOWNGRADE: {
152                                    return this.toString().replaceAll("\"", "'");
153                            }
154                            case ESCAPED: {
155                                    return this.toString().replaceAll("\"", "&quot;");
156                            }
157                            default: {
158                                    return this.toString();
159                            }
160                    }
161            }
162    
163            /**
164             * Wraps the JavaScript in Script-tag, with character set UTF-8.
165             * 
166             * @return The JavaScript wrapped in a Script-tag, with character set UTF-8
167             * @see http://www.w3schools.com/TAGS/tag_script.asp
168             */
169    
170            public String toScriptTag() {
171                    return toScriptTag("UTF-8");
172            }
173    
174            /**
175             * Wraps the JavaScript in Script-tag.
176             * 
177             * @param charset The character set to be used.
178             * @return The JavaScript wrapped in a Script-tag
179             * @see http://www.w3schools.com/TAGS/tag_script.asp
180             */
181    
182            public String toScriptTag(final String charset) {
183                    return "<script type=\"text/javascript\" charset=\"" + charset + "\">" + toString() + "</script>";
184            }
185    
186            /**
187             * Creates a Script-tag to a specific JavaScript source, with charset UTF-8.
188             * 
189             * @param source The source URI to the JavaScript code 
190             * @return a Script-tag to a specific JavaScript source, with charset UTF-8
191             * @see http://www.w3schools.com/TAGS/tag_script.asp
192             */
193    
194            public static String toScriptTagSource(final String source) {
195                    return toScriptTagSource("UTF-8", source);
196            }
197    
198            /**
199             *  Creates a Script-tag to a specific JavaScript source.
200             *  
201             * @see http://www.w3schools.com/TAGS/tag_script.asp
202             * @param charset The character set to be used.
203             * @param source The source URI to the JavaScript code 
204             * @return The JavaScript HTML tag
205             * 
206             */
207    
208            public static String toScriptTagSource(final String charset, final String source) {
209                    return "<script type=\"text/javascript\" charset=\"" + charset + "\" src=\"" + source + "\" ></script>";
210            }
211    
212            /**
213             * Checks if the JavaScript is empty.
214             * 
215             * @param html The JavaScript to check
216             * @return if the JavaScript is empty
217             */
218    
219            public static boolean isEmpty(final JavaScript html) {
220                    return html == null || html.toString().trim().length() == 0;
221            }
222    
223            /**
224             * Returns the raw JavaScript code.
225             * 
226             * @return The raw JavaScript code
227             */
228    
229            final String getCodeRaw() {
230                    return code.toString();
231            }
232    
233            /**
234             * Returns the JavaScript object name.
235             * 
236             * @return The JavaScript object name
237             */
238    
239            final String getJavaScriptObjectName() {
240                    return javaScriptObjectName;
241            }
242    
243            /**
244             * Returns the JavaScript code to call the function. JavaScriptFunction needs to be generated via the Generator class. By default a semicolon will be appended at the end.
245             * 
246             * @see Generator 
247             * @return The JavaScript code that calls the function
248             */
249    
250            final public JavaScript call() {
251                    return call(true);
252            }
253    
254            /**
255             *  Returns the JavaScript code to call the function. JavaScriptFunction needs to be generated via the Generator class.
256             *  
257             * @see Generator 
258             * @param useSemicolon If a semicolon should be appended at the end
259             * @return The JavaScript code that calls the function
260             */
261    
262            final public JavaScript call(final boolean useSemicolon) {
263    
264                    String s = StringUtil.getJavaArgumentList(parameters);
265                    String functionName = StringUtil.md5(getCodeRaw());
266    
267                    return new JavaScript(javaScriptObjectName + "." + functionName + "(" + s + ")" + (useSemicolon ? ";" : ""));
268    
269            }
270    
271    }