/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.drill.exec.compile; import org.apache.drill.exec.compile.sig.RuntimeOverridden; import org.apache.drill.exec.exception.SchemaChangeException; /** * Test case that also illustrates the proper construction of templates * with nested classes. */ public abstract class ExampleTemplateWithInner implements ExampleInner{ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ExampleTemplateWithInner.class); /** * Outer class methods can be abstract. The generated methods * replace (code merge) or override (plain-old Java) this method. */ @Override public abstract void doOutside() throws SchemaChangeException; /** * Nested classes can be static or non-static "inner" classes. * Inner classes can access fields in the outer class - a * feature not demonstrated here. * <p> * TODO: Test that use case here. */ public class TheInnerClass { /** * Because of how Drill does byte-code merging, the methods * on the inner class cannot be abstract; they must have an * empty implementation which is discarded and replaced with the * generated implementation. In plain-old Java, the generated * method overrides this one. * @throws SchemaChangeException all methods that Drill generates * throw this exception. This does not matter for byte-code merge, * but plain-old Java requires that the overridden method declare * any exceptions thrown by the overriding method. */ @RuntimeOverridden public void doInside() throws SchemaChangeException {}; /** * Not overridden. Must pass along (or handle) the SchemaChangeException * thrown by the generated method. * * @throws SchemaChangeException */ public void doDouble() throws SchemaChangeException { DoubleInner di = newDoubleInner(); di.doDouble(); } protected DoubleInner newDoubleInner() { return new DoubleInner(); } public class DoubleInner { @RuntimeOverridden public void doDouble() throws SchemaChangeException {}; } } @Override public void doInsideOutside() throws SchemaChangeException { TheInnerClass inner = newTheInnerClass(); inner.doInside(); inner.doDouble(); } /** * The byte-code merge mechanism will replace in-line calls to * <tt>new TheInnerClass</tt> with a call to create the generated * inner class. But, plain-old Java can only override methods. The * code generator will create a method of the form * <tt>new<i>InnerClassName</tt> to create the generated inner * class, which is subclass of the template inner class. The * byte-code transform technique rewrites this method to create the * generated inner class directly * @return an instance of the inner class, at runtime the generated * subclass (or replacement) of the template inner class */ protected TheInnerClass newTheInnerClass( ) { return new TheInnerClass(); } }