Java tutorial
/* * Copyright 2011, The gwtquery team. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.cgxlib.xq.rebind; /* * #%L * CGXlib * %% * Copyright (C) 2016 CGXlib (http://www.cgxlib.com) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% Code is originally from gwtquery, and modified by CGXlib team. */ import com.google.gwt.core.ext.Generator; import com.google.gwt.core.ext.GeneratorContext; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.*; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; import java.io.PrintWriter; /** * Generate lazy implementations for interface delegated to parameterized type. * The originating type implements Lazy<T> where T extends LazyBase<OriginType>. * The generator generates an implementation of T where each method returns type * T and queues up a closure which delegates execution of the method to the * OriginType. */ public class LazyGenerator extends Generator { private JClassType lazyType = null; private JClassType lazyBaseType = null; public String generate(TreeLogger treeLogger, GeneratorContext generatorContext, String requestedClass) throws UnableToCompleteException { TypeOracle oracle = generatorContext.getTypeOracle(); lazyType = oracle.findType("com.cgxlib.xq.client.Lazy"); lazyBaseType = oracle.findType("com.cgxlib.xq.client.LazyBase"); assert lazyType != null : "Can't find Lazy interface type"; assert lazyBaseType != null : "Can't find LazyBase interface type"; JClassType requestedType = oracle.findType(requestedClass); JClassType targetType = null; JClassType nonLazyType = null; for (JClassType inf : requestedType.getImplementedInterfaces()) { if (inf.isAssignableTo(lazyType)) { nonLazyType = inf.isParameterized().getTypeArgs()[0]; targetType = inf.isParameterized().getTypeArgs()[1]; break; } } if (targetType == null) return null; assert targetType != null : "Parameter of Lazy<T> not found"; String genClass = targetType.getPackage().getName() + "." + targetType.getSimpleSourceName() + getImplSuffix(); SourceWriter sw = getSourceWriter(treeLogger, generatorContext, requestedType.getPackage().getName(), targetType.getSimpleSourceName() + getImplSuffix(), targetType.getQualifiedSourceName()); if (sw != null) { generatePreamble(sw, nonLazyType.getQualifiedSourceName(), treeLogger); sw.indent(); for (JMethod method : targetType.getMethods()) { generateMethod(sw, method, nonLazyType.getQualifiedSourceName(), genClass, treeLogger); } sw.outdent(); generateDoneMethod(sw, nonLazyType, treeLogger); sw.commit(treeLogger); } return genClass; } private void generatePreamble(SourceWriter sw, String nonLazyClass, TreeLogger treeLogger) { sw.indent(); sw.println("private JsArray<JsClosure> closures = JsArray.createArray().cast();"); sw.println("private " + nonLazyClass + " ctx;"); sw.outdent(); } public String getJSNIParams(JMethod method) { String reference = "("; JParameter[] params = method.getParameters(); for (int i = 0; i < params.length; i++) { reference += params[i].getType().getJNISignature(); } reference += ")"; return reference; } public void generateMethod(SourceWriter sw, JMethod method, String nonLazyClass, String genClass, TreeLogger logger) throws UnableToCompleteException { JParameter[] params = method.getParameters(); JTypeParameter gType = method.getReturnType().isTypeParameter(); String retType = method.getReturnType().getParameterizedQualifiedSourceName(); if (gType != null) { retType = "<" + gType.getParameterizedQualifiedSourceName() + " extends " + gType.getFirstBound().getQualifiedSourceName() + "> " + retType; } sw.print("public final native " + retType + " " + method.getName()); sw.print("("); int argNum = 0; for (JParameter param : params) { sw.print((argNum == 0 ? "" : ", ") + param.getType().getParameterizedQualifiedSourceName() + " arg" + argNum); argNum++; } sw.println(") /*-{"); sw.indent(); sw.println("var self=this;"); sw.println("this.@" + genClass + "::closures.push("); sw.indent(); sw.println("function() {"); sw.indent(); sw.print("self.@" + genClass + "::ctx=self.@" + genClass + "::ctx.@" + nonLazyClass + "::" + method.getName()); sw.print(getJSNIParams(method)); sw.print("("); for (int i = 0; i < argNum; i++) { sw.print("arg" + i + (i < argNum - 1 ? "," : "")); } sw.print(")"); // special case, as() needs to invoke createLazy() if ("as".equals(method.getName())) { sw.print(".createLazy()"); } sw.println(";"); sw.outdent(); sw.println("}"); sw.outdent(); sw.println(");"); sw.println("return this;"); sw.outdent(); sw.println("}-*/;"); } protected String getImplSuffix() { return "Impl"; } protected SourceWriter getSourceWriter(TreeLogger logger, GeneratorContext context, String packageName, String className, String... interfaceNames) { PrintWriter printWriter = context.tryCreate(logger, packageName, className); if (printWriter == null) { return null; } ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(packageName, className); composerFactory.addImport("com.google.gwt.core.client.*"); composerFactory.addImport("com.cgxlib.xq.client.*"); composerFactory.addImport("com.google.gwt.dom.client.Element"); composerFactory.addImport("com.google.gwt.user.client.Event"); composerFactory.addImport("com.cgxlib.xq.client.Function"); composerFactory.addImport("com.cgxlib.xq.client.js.JsClosure"); for (String interfaceName : interfaceNames) { composerFactory.addImplementedInterface(interfaceName); } return composerFactory.createSourceWriter(context, printWriter); } // used by benchmark harness private void generateDoneMethod(SourceWriter sw, JClassType nonLazyType, TreeLogger treeLogger) { sw.indent(); sw.println("public Function done() {"); sw.indent(); sw.println("return new Function() {"); sw.indent(); sw.println("public void f() {"); sw.indent(); String classID = nonLazyType.getSimpleSourceName(); if ("XQ".equals(classID)) { classID = "CGXQUERY"; } sw.println("ctx = XQ.$(getElement()).as(" + nonLazyType.getQualifiedSourceName() + "." + classID + ");"); sw.println("for (int i = 0; i < closures.length(); i++) {"); sw.indent(); sw.println("closures.get(i).invoke();"); sw.outdent(); sw.println("}"); sw.outdent(); sw.println("}"); sw.outdent(); sw.println("};"); sw.outdent(); sw.println("}"); } }