boot/src/main/java/org/netbeans/html/boot/impl/JsCallback.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 16 Dec 2013 16:59:43 +0100
branchnetbeans
changeset 362 92fb71afdc0e
parent 358 boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java@80702021b851
child 365 5c93ad8c7a15
permissions -rw-r--r--
Moving implementation classes into org.netbeans.html namespace
jaroslav@183
     1
/**
jaroslav@358
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jaroslav@183
     3
 *
jaroslav@358
     4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
jaroslav@183
     5
 *
jaroslav@358
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@358
     7
 * Other names may be trademarks of their respective owners.
jaroslav@183
     8
 *
jaroslav@358
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@358
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@358
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@358
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@358
    13
 * License. You can obtain a copy of the License at
jaroslav@358
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@358
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@358
    16
 * specific language governing permissions and limitations under the
jaroslav@358
    17
 * License.  When distributing the software, include this License Header
jaroslav@358
    18
 * Notice in each file and include the License file at
jaroslav@358
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@358
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@358
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@358
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@358
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@358
    24
 * your own identifying information:
jaroslav@358
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@358
    26
 *
jaroslav@358
    27
 * Contributor(s):
jaroslav@358
    28
 *
jaroslav@358
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@358
    30
 * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
jaroslav@358
    31
 *
jaroslav@358
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@358
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@358
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@358
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@358
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@358
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@358
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@358
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@358
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@358
    41
 * made subject to such option by the copyright holder.
jaroslav@183
    42
 */
jaroslav@362
    43
package org.netbeans.html.boot.impl;
jaroslav@183
    44
jaroslav@183
    45
jaroslav@183
    46
/**
jaroslav@183
    47
 *
jaroslav@183
    48
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@183
    49
 */
jaroslav@184
    50
abstract class JsCallback {
jaroslav@184
    51
    final String parse(String body) {
jaroslav@183
    52
        StringBuilder sb = new StringBuilder();
jaroslav@183
    53
        int pos = 0;
jaroslav@183
    54
        for (;;) {
jaroslav@183
    55
            int next = body.indexOf(".@", pos);
jaroslav@183
    56
            if (next == -1) {
jaroslav@183
    57
                sb.append(body.substring(pos));
jaroslav@191
    58
                body = sb.toString();
jaroslav@191
    59
                break;
jaroslav@183
    60
            }
jaroslav@183
    61
            int ident = next;
jaroslav@188
    62
            while (ident > 0) {
jaroslav@188
    63
                if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
jaroslav@188
    64
                    ident++;
jaroslav@188
    65
                    break;
jaroslav@188
    66
                }
jaroslav@183
    67
            }
jaroslav@183
    68
            String refId = body.substring(ident, next);
jaroslav@183
    69
            
jaroslav@183
    70
            sb.append(body.substring(pos, ident));
jaroslav@183
    71
            
jaroslav@183
    72
            int sigBeg = body.indexOf('(', next);
jaroslav@183
    73
            int sigEnd = body.indexOf(')', sigBeg);
jaroslav@183
    74
            int colon4 = body.indexOf("::", next);
jaroslav@183
    75
            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
jaroslav@273
    76
                throw new IllegalStateException(
jaroslav@273
    77
                    "Wrong format of instance callback. "
jaroslav@273
    78
                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
jaroslav@273
    79
                    + body
jaroslav@273
    80
                );
jaroslav@183
    81
            }
jaroslav@183
    82
            String fqn = body.substring(next + 2, colon4);
jaroslav@183
    83
            String method = body.substring(colon4 + 2, sigBeg);
jaroslav@183
    84
            String params = body.substring(sigBeg, sigEnd + 1);
jaroslav@188
    85
jaroslav@188
    86
            int paramBeg = body.indexOf('(', sigEnd + 1);
jaroslav@195
    87
            if (paramBeg == -1) {
jaroslav@273
    88
                throw new IllegalStateException(
jaroslav@273
    89
                    "Wrong format of instance callback. "
jaroslav@273
    90
                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
jaroslav@273
    91
                    + body
jaroslav@273
    92
                );
jaroslav@195
    93
            }
jaroslav@183
    94
            
jaroslav@184
    95
            sb.append(callMethod(refId, fqn, method, params));
jaroslav@188
    96
            if (body.charAt(paramBeg + 1) != (')')) {
jaroslav@188
    97
                sb.append(",");
jaroslav@188
    98
            }
jaroslav@188
    99
            pos = paramBeg + 1;
jaroslav@183
   100
        }
jaroslav@191
   101
        pos = 0;
jaroslav@191
   102
        sb = null;
jaroslav@191
   103
        for (;;) {
jaroslav@191
   104
            int next = body.indexOf("@", pos);
jaroslav@191
   105
            if (next == -1) {
jaroslav@191
   106
                if (sb == null) {
jaroslav@191
   107
                    return body;
jaroslav@191
   108
                }
jaroslav@191
   109
                sb.append(body.substring(pos));
jaroslav@191
   110
                return sb.toString();
jaroslav@191
   111
            }
jaroslav@191
   112
            if (sb == null) {
jaroslav@191
   113
                sb = new StringBuilder();
jaroslav@191
   114
            }
jaroslav@191
   115
            
jaroslav@191
   116
            sb.append(body.substring(pos, next));
jaroslav@191
   117
            
jaroslav@191
   118
            int sigBeg = body.indexOf('(', next);
jaroslav@191
   119
            int sigEnd = body.indexOf(')', sigBeg);
jaroslav@191
   120
            int colon4 = body.indexOf("::", next);
jaroslav@191
   121
            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
jaroslav@273
   122
                throw new IllegalStateException(
jaroslav@273
   123
                    "Wrong format of static callback. "
jaroslav@273
   124
                    + "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n" 
jaroslav@273
   125
                    + body
jaroslav@273
   126
                );
jaroslav@191
   127
            }
jaroslav@191
   128
            String fqn = body.substring(next + 1, colon4);
jaroslav@191
   129
            String method = body.substring(colon4 + 2, sigBeg);
jaroslav@191
   130
            String params = body.substring(sigBeg, sigEnd + 1);
jaroslav@191
   131
jaroslav@191
   132
            int paramBeg = body.indexOf('(', sigEnd + 1);
jaroslav@191
   133
            
jaroslav@191
   134
            sb.append(callMethod(null, fqn, method, params));
jaroslav@191
   135
            pos = paramBeg + 1;
jaroslav@191
   136
        }
jaroslav@183
   137
    }
jaroslav@183
   138
jaroslav@184
   139
    protected abstract CharSequence callMethod(
jaroslav@183
   140
        String ident, String fqn, String method, String params
jaroslav@184
   141
    );
jaroslav@186
   142
jaroslav@186
   143
    static String mangle(String fqn, String method, String params) {
jaroslav@188
   144
        if (params.startsWith("(")) {
jaroslav@188
   145
            params = params.substring(1);
jaroslav@188
   146
        }
jaroslav@188
   147
        if (params.endsWith(")")) {
jaroslav@188
   148
            params = params.substring(0, params.length() - 1);
jaroslav@188
   149
        }
jaroslav@186
   150
        return 
jaroslav@194
   151
            replace(fqn) + "$" + replace(method) + "$" + replace(params);
jaroslav@186
   152
    }
jaroslav@186
   153
    
jaroslav@186
   154
    private static String replace(String orig) {
jaroslav@186
   155
        return orig.replace("_", "_1").
jaroslav@186
   156
            replace(";", "_2").
jaroslav@186
   157
            replace("[", "_3").
jaroslav@186
   158
            replace('.', '_').replace('/', '_');
jaroslav@186
   159
    }
jaroslav@183
   160
}