// Code generated by gobind. DO NOT EDIT.

// Java class doc.NoDoc is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java doc
package doc;

import go.Seq;

/**
 * A generic comment with &lt;HTML&gt;.
 */
public final class NoDoc implements Seq.Proxy {
    static { Doc.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    NoDoc(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
    
    public NoDoc() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
    
    private static native int __New();
    
    @Override public boolean equals(Object o) {
        if (o == null || !(o instanceof NoDoc)) {
            return false;
        }
        NoDoc that = (NoDoc)o;
        return true;
    }
    
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(new Object[] {});
    }
    
    @Override public String toString() {
        StringBuilder b = new StringBuilder();
        b.append("NoDoc").append("{");
        return b.append("}").toString();
    }
}

// Code generated by gobind. DO NOT EDIT.

// Java class doc.S is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java doc
package doc;

import go.Seq;

/**
 * S is a struct.
 */
public final class S implements Seq.Proxy {
    static { Doc.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    /**
     * NewS is a constructor.
     */
    public S() {
        this.refnum = __NewS();
        Seq.trackGoRef(refnum, this);
    }
    
    private static native int __NewS();
    
    S(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
    
    /**
     * SF is a field.
     */
    public final native String getSF();
    /**
     * SF is a field.
     */
    public final native void setSF(String v);
    
    /**
     * Anonymous field.
     */
    public final native S2 getS2();
    /**
     * Anonymous field.
     */
    public final native void setS2(S2 v);
    
    /**
     * Multiple fields.
     */
    public final native String getF1();
    /**
     * Multiple fields.
     */
    public final native void setF1(String v);
    
    /**
     * Multiple fields.
     */
    public final native String getF2();
    /**
     * Multiple fields.
     */
    public final native void setF2(String v);
    
    /**
     * After is another method.
     */
    public native void after();
    public native void before();
    @Override public boolean equals(Object o) {
        if (o == null || !(o instanceof S)) {
            return false;
        }
        S that = (S)o;
        String thisSF = getSF();
        String thatSF = that.getSF();
        if (thisSF == null) {
            if (thatSF != null) {
                return false;
            }
        } else if (!thisSF.equals(thatSF)) {
            return false;
        }
        S2 thisS2 = getS2();
        S2 thatS2 = that.getS2();
        if (thisS2 == null) {
            if (thatS2 != null) {
                return false;
            }
        } else if (!thisS2.equals(thatS2)) {
            return false;
        }
        String thisF1 = getF1();
        String thatF1 = that.getF1();
        if (thisF1 == null) {
            if (thatF1 != null) {
                return false;
            }
        } else if (!thisF1.equals(thatF1)) {
            return false;
        }
        String thisF2 = getF2();
        String thatF2 = that.getF2();
        if (thisF2 == null) {
            if (thatF2 != null) {
                return false;
            }
        } else if (!thisF2.equals(thatF2)) {
            return false;
        }
        return true;
    }
    
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(new Object[] {getSF(), getS2(), getF1(), getF2()});
    }
    
    @Override public String toString() {
        StringBuilder b = new StringBuilder();
        b.append("S").append("{");
        b.append("SF:").append(getSF()).append(",");
        b.append("S2:").append(getS2()).append(",");
        b.append("F1:").append(getF1()).append(",");
        b.append("F2:").append(getF2()).append(",");
        return b.append("}").toString();
    }
}

// Code generated by gobind. DO NOT EDIT.

// Java class doc.S2 is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java doc
package doc;

import go.Seq;

/**
 * S2 is a struct.
 */
public final class S2 implements Seq.Proxy {
    static { Doc.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    S2(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
    
    public S2() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
    
    private static native int __New();
    
    @Override public boolean equals(Object o) {
        if (o == null || !(o instanceof S2)) {
            return false;
        }
        S2 that = (S2)o;
        return true;
    }
    
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(new Object[] {});
    }
    
    @Override public String toString() {
        StringBuilder b = new StringBuilder();
        b.append("S2").append("{");
        return b.append("}").toString();
    }
}

// Code generated by gobind. DO NOT EDIT.

// Java class doc.I is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java doc
package doc;

import go.Seq;

/**
 * I is an interface.
 */
public interface I {
    /**
     * IM is a method.
     */
    public void im();
    
}

// Code generated by gobind. DO NOT EDIT.

// Java class doc.Doc is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java doc
package doc;

import go.Seq;

public abstract class Doc {
    static {
        Seq.touch(); // for loading the native library
        _init();
    }
    
    private Doc() {} // uninstantiable
    
    // touch is called from other bound packages to initialize this package
    public static void touch() {}
    
    private static native void _init();
    
    private static final class proxyI implements Seq.Proxy, I {
        private final int refnum;
        
        @Override public final int incRefnum() {
              Seq.incGoRef(refnum, this);
              return refnum;
        }
        
        proxyI(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
        
        public native void im();
    }
    
    /**
     * C is a constant.
     */
    public static final boolean C = true;
    
    /**
     * A group of vars.
     */
    public static native void setNoDocVar(double v);
    /**
     * A group of vars.
     */
    public static native double getNoDocVar();
    
    /**
     * A specific var.
     */
    public static native void setSpecific(String v);
    /**
     * A specific var.
     */
    public static native String getSpecific();
    
    /**
     * V is a var.
     */
    public static native void setV(String v);
    /**
     * V is a var.
     */
    public static native String getV();
    
    /**
     * F is a function.
     */
    public static native void f();
    /**
     * NewS is a constructor.
     */
    public static native S newS();
}
