Package com4j.tlbimp

Source Code of com4j.tlbimp.InvocableInterfaceGenerator$MethodBinderImpl

package com4j.tlbimp;

import com4j.ReturnValue;
import com4j.tlbimp.Generator.LibBinder;
import com4j.tlbimp.def.IDispInterfaceDecl;
import com4j.tlbimp.def.IInterface;
import com4j.tlbimp.def.IInterfaceDecl;
import com4j.tlbimp.def.IMethod;
import com4j.tlbimp.def.IPtrType;
import com4j.tlbimp.def.IType;

import java.util.ArrayList;
import java.util.List;

/**
* Common code for generating interfaces that user application calls.
*
* <p>
* Namely the common code between {@link CustomInterfaceGenerator}
* and {@link DispInterfaceGenerator}.
*
* @author Kohsuke Kawaguchi
*/
abstract class InvocableInterfaceGenerator<T extends IInterface> extends InterfaceGenerator<T> {
    protected InvocableInterfaceGenerator(LibBinder lib, T t) {
        super(lib, t);
    }

    @Override
    protected final String getClassDecl() {
        return "public interface";
    }

    @Override
    protected final void generateMethod(IMethod m, IndentingWriter o) throws BindingException {
        try {
            MethodBinderImpl mb = createMethodBinder(m);
            if(mb==null)        return;
            mb.declare(o);
            o.println();

            mb.generateDefaultInterfaceFacade(o);
        } catch (BindingException e) {
            e.addContext("method "+m.getName());
            throw e;
        }
    }

    @Override
    protected final void generateExtends(IndentingWriter o) {
        boolean hasEnum = false;
        for( int j=0; j<t.countMethods() && !hasEnum; j++ ) {
            IMethod m = t.getMethod(j);
            hasEnum = MethodBinder.isEnum(m);
        }

        List<String> baseTypes = getBaseTypes();
        if(baseTypes.isEmpty()) {
            // if it has a base type, it indirectly inherits Com4jObject,
            // so no point in declaring it explicitly.
            baseTypes.add("Com4jObject");
        }
        if(hasEnum) {
            baseTypes.add("Iterable<Com4jObject>");
        }

        o.print(" extends ");
        o.beginCommaMode();
        for (String name : baseTypes) {
            o.comma();
            o.print(name);
        }
        o.endCommaMode();
    }

    /**
     * Returns a {@link MethodBinderImpl} that generates a method definition.
     *
     * @return
     *      null to skip the generation
     */
    protected abstract MethodBinderImpl createMethodBinder(IMethod m) throws BindingException;


    /**
     * Partially implemented common {@link MethodBinder} implementation.
     */
    protected abstract class MethodBinderImpl extends MethodBinder {
        protected MethodBinderImpl(Generator g, IMethod method) throws BindingException {
            super(g, method);
        }

        @Override
        protected final void terminate(IndentingWriter o) {
            o.println(";");
        }

        /**
         * Generates a method that uses {@link ReturnValue#defaultPropertyThrough()}
         * if applicable, or otherwise no-op.
         */
        final void generateDefaultInterfaceFacade( IndentingWriter o ) throws BindingException {
            IMethod m = method;
            List<IType> intermediates = new ArrayList<IType>();

            while(true) {
                MethodBinderImpl mb = createMethodBinder(m);
                // only handle methods of the form "HRESULT foo([out,retval]IFoo** ppOut);
                if (m.getParamCount() != 1 || mb.retParam != 0 || mb.params[mb.retParam].isIn())
                    break;

                // we expect it to be an interface pointer.
                IPtrType pt = mb.returnType.queryInterface(IPtrType.class);
                IDispInterfaceDecl di = null;
                IInterfaceDecl ii = null;
                if (pt != null) {
                    IType t = pt.getPointedAtType();
                    di = t.queryInterface(IDispInterfaceDecl.class);
                    ii = t.queryInterface(IInterfaceDecl.class);
                }

                if (di == null && ii == null)
                    break;

                IInterface intf;
                if (ii != null) {
                    intf = ii;
                } else {
                    if(di.isDual())
                        intf = di.getVtblInterface();
                    else
                        break;
                }

                // does this target interface has a default method?
                IMethod dm = g.dmf.getDefaultMethod(intf);
                if (dm == null)
                    return;

                // recursively check...
                m = dm;
                intermediates.add(pt);
            }

            if(intermediates.isEmpty())
                return; // no default method to generate

            if(m.getParamCount()<2)
                return; // the default method has to have at least one in param and one ret val

            o.printf("@VTID(%1d)",
                method.getVtableIndex());
            o.println();

            MethodBinderImpl mb = createMethodBinder(m);
            mb.declareReturnType(o,intermediates);
            this.declareMethodName(o);
            mb.declareParameters(o);
            o.println();
        }
    }
}
TOP

Related Classes of com4j.tlbimp.InvocableInterfaceGenerator$MethodBinderImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.