001    /*
002     * Copyright 2006 Google Inc.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package com.google.gwt.core.ext;
017    
018    /**
019     * Generates source code for subclasses during deferred binding requests.
020     * Subclasses must be thread-safe.
021     */
022    public abstract class Generator {
023    
024      /**
025       * Generate a default constructible subclass of the requested type.
026       * 
027       * @return the name of a subclass to substitute for the requested class, or
028       *         return <code>null</code> to cause the requested type itself to be
029       *         used
030       * @throws UnableToCompleteException if for any reason the generator cannot
031       *           provide a substitute class
032       */
033      public abstract String generate(TreeLogger logger, GeneratorContext context,
034          String typeName) throws UnableToCompleteException;
035    
036      /**
037       * Escapes string content to be a valid string literal.
038       * @return an escaped version of <code>unescaped</code>, suitable for being 
039       * enclosed in double quotes in Java source
040       */
041      public static String escape(String unescaped) {
042        int extra = 0;
043        for (int in = 0, n = unescaped.length(); in < n; ++in) {
044          switch (unescaped.charAt(in)) {
045            case '\n':
046            case '\r':
047            case '\"':
048            case '\\':
049              ++extra;
050              break;
051          }
052        }
053    
054        if (extra == 0) {
055          return unescaped;
056        }
057    
058        char[] oldChars = unescaped.toCharArray();
059        char[] newChars = new char[oldChars.length + extra];
060        for (int in = 0, out = 0, n = oldChars.length; in < n; ++in, ++out) {
061          char c = oldChars[in];
062          switch (c) {
063            case '\n':
064              newChars[out++] = '\\';
065              c = 'n';
066              break;
067            case '\r':
068              newChars[out++] = '\\';
069              c = 'r';
070              break;
071            case '\"':
072              newChars[out++] = '\\';
073              c = '"';
074              break;
075            case '\\':
076              newChars[out++] = '\\';
077              c = '\\';
078              break;
079          }
080          newChars[out] = c;
081        }
082    
083        return String.valueOf(newChars);
084      }
085    }