/*
 * All rights reserved.
 *
 */
package org.kohsuke.stapler.jsp;

import org.kohsuke.stapler.Facet;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.Dispatcher;
import org.kohsuke.stapler.RequestImpl;
import org.kohsuke.stapler.ResponseImpl;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.MetaInfServices;
import org.kohsuke.stapler.lang.Klass;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import java.util.List;
import java.util.logging.Level;
import java.io.IOException;

/**
 * {@link Facet} that adds JSP file support.
 *
 * @author Kohsuke Kawaguchi
 */
@MetaInfServices
public class JSPFacet extends Facet {

    public void buildViewDispatchers(MetaClass owner, List<Dispatcher> dispatchers) {
        dispatchers.add(new Dispatcher() {

            public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException {
                String next = req.tokens.peek();
                if (next == null)
                    return false;
                // only match the end of the URL
                if (req.tokens.countRemainingTokens() > 1)
                    return false;
                // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different
                if (req.getRequestURI().endsWith("/"))
                    return false;
                Stapler stapler = req.getStapler();
                if (!isBasename(next)) {
                    // potentially an attempt to make a folder traversal
                    return false;
                }
                // check static resources
                RequestDispatcher disp = createRequestDispatcher(req, node.getClass(), node, next);
                if (disp == null) {
                    // check JSP views
                    disp = createRequestDispatcher(req, node.getClass(), node, next + ".jsp");
                    if (disp == null)
                        return false;
                }
                req.tokens.next();
                if (traceable())
                    trace(req, rsp, "Invoking " + next + ".jsp" + " on " + node + " for " + req.tokens);
                stapler.forward(disp, req, rsp);
                return true;
            }

{
                return "TOKEN.jsp for url=/TOKEN/...";
            }
        });
    }

    public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException {
        ServletContext context = request.stapler.getServletContext();
        // JSP support is deprecated, and this doesn't work with non-Java objects
        for (Class c = type.toJavaClass(); c != Object.class; c = c.getSuperclass()) {
            String name = "/WEB-INF/side-files/" + c.getName().replace('.', '/').replace('$', '/') + '/' + viewName;
            if (context.getResource(name) != null) {
                // Tomcat returns a RequestDispatcher even if the JSP file doesn't exist.
                // so check if the resource exists first.
                RequestDispatcher disp = context.getRequestDispatcher(name);
                if (disp != null) {
                    return new RequestDispatcherWrapper(disp, it);
                }
            }
        }
        return null;
    }

    public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass nodeMetaClass) throws IOException, ServletException {
        Stapler stapler = req.stapler;
        // TODO: find the list of welcome pages for this class by reading web.xml
        RequestDispatcher indexJsp = createRequestDispatcher(req, node.getClass(), node, "index.jsp");
        if (indexJsp != null) {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine("Invoking index.jsp on " + node);
            stapler.forward(indexJsp, req, rsp);
            return true;
        }
        return false;
    }
}


{
        Stapler stapler = req.stapler;
        // TODO: find the list of welcome pages for this class by reading web.xml
        RequestDispatcher indexJsp = createRequestDispatcher(req, node.getClass(), node, "index.jsp");
        if (indexJsp != null) {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine("Invoking index.jsp on " + node);
            stapler.forward(indexJsp, req, rsp);
            return true;
        }
        return false;
    }

/*
 * All rights reserved.
 *
 */
package org.kohsuke.stapler.jsp;

import org.kohsuke.stapler.Facet;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.Dispatcher;
import org.kohsuke.stapler.RequestImpl;
import org.kohsuke.stapler.ResponseImpl;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.MetaInfServices;
import org.kohsuke.stapler.lang.Klass;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import java.util.List;
import java.util.logging.Level;
import java.io.IOException;

/**
 * {@link Facet} that adds JSP file support.
 *
 * @author Kohsuke Kawaguchi
 */
@MetaInfServices
public class JSPFacet extends Facet {

    public void buildViewDispatchers(MetaClass owner, List<Dispatcher> dispatchers) {
        dispatchers.add(new Dispatcher() {

            public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException {
                String next = req.tokens.peek();
                if (next == null)
                    return false;
                // only match the end of the URL
                if (req.tokens.countRemainingTokens() > 1)
                    return false;
                // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different
                if (req.getRequestURI().endsWith("/"))
                    return false;
                Stapler stapler = req.getStapler();
                if (!isBasename(next)) {
                    // potentially an attempt to make a folder traversal
                    return false;
                }
                // check static resources
                RequestDispatcher disp = createRequestDispatcher(req, node.getClass(), node, next);
                if (disp == null) {
                    // check JSP views
                    disp = createRequestDispatcher(req, node.getClass(), node, next + ".jsp");
                    if (disp == null)
                        return false;
                }
                req.tokens.next();
                if (traceable())
                    trace(req, rsp, "Invoking " + next + ".jsp" + " on " + node + " for " + req.tokens);
                stapler.forward(disp, req, rsp);
                return true;
            }

            public String toString() {
                return "TOKEN.jsp for url=/TOKEN/...";
            }
        });
    }

    public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException {
        ServletContext context = request.stapler.getServletContext();
        // JSP support is deprecated, and this doesn't work with non-Java objects
        for (Class c = type.toJavaClass(); c != Object.class; c = c.getSuperclass()) {
            String name = "/WEB-INF/side-files/" + c.getName().replace('.', '/').replace('$', '/') + '/' + viewName;
            if (context.getResource(name) != null) {
                // Tomcat returns a RequestDispatcher even if the JSP file doesn't exist.
                // so check if the resource exists first.
                RequestDispatcher disp = context.getRequestDispatcher(name);
                if (disp != null) {
                    return new RequestDispatcherWrapper(disp, it);
                }
            }
        }
        return null;
    }

    public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass nodeMetaClass) throws IOException, ServletException


        Stapler stapler = req.stapler;
        // TODO: find the list of welcome pages for this class by reading web.xml

/*
 * All rights reserved.
 *
 */
package org.kohsuke.stapler.jsp;

import org.kohsuke.stapler.Facet;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.Dispatcher;
import org.kohsuke.stapler.RequestImpl;
import org.kohsuke.stapler.ResponseImpl;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.MetaInfServices;
import org.kohsuke.stapler.lang.Klass;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import java.util.List;
import java.util.logging.Level;
import java.io.IOException;

/**
 * {@link Facet} that adds JSP file support.
 *
 * @author Kohsuke Kawaguchi
 */
@MetaInfServices
public class JSPFacet extends Facet {

    public void buildViewDispatchers(MetaClass owner, List<Dispatcher> dispatchers) {
        dispatchers.add(new Dispatcher() {

            public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException {
                String next = req.tokens.peek();
                if (next == null)
                    return false;
                // only match the end of the URL
                if (req.tokens.countRemainingTokens() > 1)
                    return false;
                // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different
                if (req.getRequestURI().endsWith("/"))
                    return false;
                Stapler stapler = req.getStapler();
                if (!isBasename(next)) {
                    // potentially an attempt to make a folder traversal
                    return false;
                }
                // check static resources
                RequestDispatcher disp = createRequestDispatcher(req, node.getClass(), node, next);
                if (disp == null) {
                    // check JSP views
                    disp = createRequestDispatcher(req, node.getClass(), node, next + ".jsp");
                    if (disp == null)
                        return false;
                }
                req.tokens.next();
                if (traceable())
                    trace(req, rsp, "Invoking " + next + ".jsp" + " on " + node + " for " + req.tokens);
                stapler.forward(disp, req, rsp);
                return true;
            }

            public String toString() {
                return "TOKEN.jsp for url=/TOKEN/...";
            }
        });
    }

    public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException {
        ServletContext context = request.stapler.getServletContext();
        // JSP support is deprecated, and this doesn't work with non-Java objects
        for (Class c = type.toJavaClass(); c != Object.class; c = c.getSuperclass()) {
            String name = "/WEB-INF/side-files/" + c.getName().replace('.', '/').replace('$', '/') + '/' + viewName;
            if (context.getResource(name) != null) {
                // Tomcat returns a RequestDispatcher even if the JSP file doesn't exist.
                // so check if the resource exists first.
                RequestDispatcher disp = context.getRequestDispatcher(name);
                if (disp != null) {
                    return new RequestDispatcherWrapper(disp, it);
                }
            }
        }
        return null;
    }

    public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass nodeMetaClass) throws IOException, ServletException {

        RequestDispatcher indexJsp = createRequestDispatcher(req, node.getClass(), node, "index.jsp");
        if (indexJsp != null) {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine("Invoking index.jsp on " + node);
            stapler.forward(indexJsp, req, rsp);
            return true;
        }
        return false;
    }
}


RequestDispatcher indexJsp = createRequestDispatcher(req, node.getClass(), node, "index.jsp");
        if (indexJsp != null) {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine("Invoking index.jsp on " + node);
            stapler.forward(indexJsp, req, rsp);
            return true;
        }

/*
 * All rights reserved.
 *
 */
package org.kohsuke.stapler.jsp;

import org.kohsuke.stapler.Facet;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.Dispatcher;
import org.kohsuke.stapler.RequestImpl;
import org.kohsuke.stapler.ResponseImpl;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.MetaInfServices;
import org.kohsuke.stapler.lang.Klass;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import java.util.List;
import java.util.logging.Level;
import java.io.IOException;

/**
 * {@link Facet} that adds JSP file support.
 *
 * @author Kohsuke Kawaguchi
 */
@MetaInfServices
public class JSPFacet extends Facet {

    public void buildViewDispatchers(MetaClass owner, List<Dispatcher> dispatchers) {
        dispatchers.add(new Dispatcher() {

            public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException {
                String next = req.tokens.peek();
                if (next == null)
                    return false;
                // only match the end of the URL
                if (req.tokens.countRemainingTokens() > 1)
                    return false;
                // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different
                if (req.getRequestURI().endsWith("/"))
                    return false;
                Stapler stapler = req.getStapler();
                if (!isBasename(next)) {
                    // potentially an attempt to make a folder traversal
                    return false;
                }
                // check static resources
                RequestDispatcher disp = createRequestDispatcher(req, node.getClass(), node, next);
                if (disp == null) {
                    // check JSP views
                    disp = createRequestDispatcher(req, node.getClass(), node, next + ".jsp");
                    if (disp == null)
                        return false;
                }
                req.tokens.next();
                if (traceable())
                    trace(req, rsp, "Invoking " + next + ".jsp" + " on " + node + " for " + req.tokens);
                stapler.forward(disp, req, rsp);
                return true;
            }

            public String toString() {
                return "TOKEN.jsp for url=/TOKEN/...";
            }
        });
    }

    public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException {
        ServletContext context = request.stapler.getServletContext();
        // JSP support is deprecated, and this doesn't work with non-Java objects
        for (Class c = type.toJavaClass(); c != Object.class; c = c.getSuperclass()) {
            String name = "/WEB-INF/side-files/" + c.getName().replace('.', '/').replace('$', '/') + '/' + viewName;
            if (context.getResource(name) != null) {
                // Tomcat returns a RequestDispatcher even if the JSP file doesn't exist.
                // so check if the resource exists first.
                RequestDispatcher disp = context.getRequestDispatcher(name);
                if (disp != null) {
                    return new RequestDispatcherWrapper(disp, it);
                }
            }
        }
        return null;
    }

    public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass nodeMetaClass) throws IOException, ServletException {
        Stapler stapler = req.stapler;
        // TODO: find the list of welcome pages for this class by reading web.xml


/*
 * All rights reserved.
 *
 */
package org.kohsuke.stapler.jsp;

import org.kohsuke.stapler.Facet;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.Dispatcher;
import org.kohsuke.stapler.RequestImpl;
import org.kohsuke.stapler.ResponseImpl;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.MetaInfServices;
import org.kohsuke.stapler.lang.Klass;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import java.util.List;
import java.util.logging.Level;
import java.io.IOException;

/**
 * {@link Facet} that adds JSP file support.
 *
 * @author Kohsuke Kawaguchi
 */
@MetaInfServices
public class JSPFacet extends Facet {

    public void buildViewDispatchers(MetaClass owner, List<Dispatcher> dispatchers) {
        dispatchers.add(new Dispatcher() {

            public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException {
                String next = req.tokens.peek();
                if (next == null)
                    return false;
                // only match the end of the URL
                if (req.tokens.countRemainingTokens() > 1)
                    return false;
                // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different
                if (req.getRequestURI().endsWith("/"))
                    return false;
                Stapler stapler = req.getStapler();
                if (!isBasename(next)) {
                    // potentially an attempt to make a folder traversal
                    return false;
                }
                // check static resources
                RequestDispatcher disp = createRequestDispatcher(req, node.getClass(), node, next);
                if (disp == null) {
                    // check JSP views
                    disp = createRequestDispatcher(req, node.getClass(), node, next + ".jsp");
                    if (disp == null)
                        return false;
                }
                req.tokens.next();
                if (traceable())
                    trace(req, rsp, "Invoking " + next + ".jsp" + " on " + node + " for " + req.tokens);
                stapler.forward(disp, req, rsp);
                return true;
            }

            public String toString() {
                return "TOKEN.jsp for url=/TOKEN/...";
            }
        });
    }

    public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException {
        ServletContext context = request.stapler.getServletContext();
        // JSP support is deprecated, and this doesn't work with non-Java objects
        for (Class c = type.toJavaClass(); c != Object.class; c = c.getSuperclass()) {
            String name = "/WEB-INF/side-files/" + c.getName().replace('.', '/').replace('$', '/') + '/' + viewName;
            if (context.getResource(name) != null) {
                // Tomcat returns a RequestDispatcher even if the JSP file doesn't exist.
                // so check if the resource exists first.
                RequestDispatcher disp = context.getRequestDispatcher(name);
                if (disp != null) {
                    return new RequestDispatcherWrapper(disp, it);
                }
            }
        }
        return null;
    }

    public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass nodeMetaClass) throws IOException, ServletException {
        Stapler stapler = req.stapler;
        // TODO: find the list of welcome pages for this class by reading web.xml
        RequestDispatcher indexJsp = createRequestDispatcher(req, node.getClass(), node, "index.jsp");
        if (indexJsp != null) {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine("Invoking index.jsp on " + node);
            stapler.forward(indexJsp, req, rsp);
            return true;
        }


/*
 * All rights reserved.
 *
 */
package org.kohsuke.stapler.jsp;

import org.kohsuke.stapler.Facet;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.Dispatcher;
import org.kohsuke.stapler.RequestImpl;
import org.kohsuke.stapler.ResponseImpl;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.MetaInfServices;
import org.kohsuke.stapler.lang.Klass;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import java.util.List;
import java.util.logging.Level;
import java.io.IOException;

/**
 * {@link Facet} that adds JSP file support.
 *
 * @author Kohsuke Kawaguchi
 */
@MetaInfServices
public class JSPFacet extends Facet {

    public void buildViewDispatchers(MetaClass owner, List<Dispatcher> dispatchers) {
        dispatchers.add(new Dispatcher() {

            public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException {
                String next = req.tokens.peek();
                if (next == null)
                    return false;
                // only match the end of the URL
                if (req.tokens.countRemainingTokens() > 1)
                    return false;
                // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different
                if (req.getRequestURI().endsWith("/"))
                    return false;
                Stapler stapler = req.getStapler();
                if (!isBasename(next)) {
                    // potentially an attempt to make a folder traversal
                    return false;
                }
                // check static resources
                RequestDispatcher disp = createRequestDispatcher(req, node.getClass(), node, next);
                if (disp == null) {
                    // check JSP views
                    disp = createRequestDispatcher(req, node.getClass(), node, next + ".jsp");
                    if (disp == null)
                        return false;
                }
                req.tokens.next();
                if (traceable())
                    trace(req, rsp, "Invoking " + next + ".jsp" + " on " + node + " for " + req.tokens);
                stapler.forward(disp, req, rsp);
                re

            }

            public String toString() {
                return "TOKEN.jsp for url=/TOKEN/...";
            }
        });
    }

    public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException {
        ServletContext context = request.stapler.getServletContext();
        // JSP support is deprecated, and this doesn't work with non-Java objects
        for (Class c = type.toJavaClass(); c != Object.class; c = c.getSuperclass()) {
            String name = "/WEB-INF/side-files/" + c.getName().replace('.', '/').replace('$', '/') + '/' + viewName;
            if (context.getResource(name) != null) {
                // Tomcat returns a RequestDispatcher even if the JSP file doesn't exist.
                // so check if the resource exists first.
                RequestDispatcher disp = context.getRequestDispatcher(name);
                if (disp != null) {
                    return new RequestDispatcherWrapper(disp, it);
                }
            }
        }
        return null;
    }

    public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass nodeMetaClass) throws IOException, ServletException {
        Stapler stapler = req.stapler;
        // TODO: find the list of welcome pages for this class by reading web.xml
        RequestDispatcher indexJsp = createRequestDispatcher(req, node.getClass(), node, "index.jsp");
        if (indexJsp != null) {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine("Invoking index.jsp on " + node);
            stapler.forward(indexJsp, req, rsp);
            return true;
        }
        return false;
    }
}


if (traceable())
                    trace(req, rsp, "Invoking " + next + ".jsp" + " on " + node + " for " + req.tokens);

/*
 * All rights reserved.
 *
 */
package org.kohsuke.stapler.jsp;

import org.kohsuke.stapler.Facet;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.Dispatcher;
import org.kohsuke.stapler.RequestImpl;
import org.kohsuke.stapler.ResponseImpl;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.MetaInfServices;
import org.kohsuke.stapler.lang.Klass;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import java.util.List;
import java.util.logging.Level;
import java.io.IOException;

/**
 * {@link Facet} that adds JSP file support.
 *
 * @author Kohsuke Kawaguchi
 */
@MetaInfServices
public class JSPFacet extends Facet {

    public void buildViewDispatchers(MetaClass owner, List<Dispatcher> dispatchers) {
        dispatchers.add(new Dispatcher() {

            public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException {
                String next = req.tokens.peek();
                if (next == null)
                    return false;
                // only match the end of the URL
                if (req.tokens.countRemainingTokens() > 1)
                    return false;
                // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different
                if (req.getRequestURI().endsWith("/"))
                    return false;
                Stapler stapler = req.getStapler();
                if (!isBasename(next)) {
                    // potentially an attempt to make a folder traversal
                    return false;
                }
                // check static resources
                RequestDispatcher disp = createRequestDispatcher(req, node.getClass(), node, next);
                if (disp == null) {
                    // check JSP views
                    disp = createRequestDispatcher(req, node.getClass(), node, next + ".jsp");
                    if (disp == null)
                        return false;
                }
                req.tokens.next();

                stapler.forward(disp, req, rsp);
                return true;
            }

            public String toString() {
                return "TOKEN.jsp for url=/TOKEN/...";
            }
        });
    }

    public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException {
        ServletContext context = request.stapler.getServletContext();
        // JSP support is deprecated, and this doesn't work with non-Java objects
        for (Class c = type.toJavaClass(); c != Object.class; c = c.getSuperclass()) {
            String name = "/WEB-INF/side-files/" + c.getName().replace('.', '/').replace('$', '/') + '/' + viewName;
            if (context.getResource(name) != null) {
                // Tomcat returns a RequestDispatcher even if the JSP file doesn't exist.
                // so check if the resource exists first.
                RequestDispatcher disp = context.getRequestDispatcher(name);
                if (disp != null) {
                    return new RequestDispatcherWrapper(disp, it);
                }
            }
        }
        return null;
    }

    public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass nodeMetaClass) throws IOException, ServletException {
        Stapler stapler = req.stapler;
        // TODO: find the list of welcome pages for this class by reading web.xml
        RequestDispatcher indexJsp = createRequestDispatcher(req, node.getClass(), node, "index.jsp");
        if (indexJsp != null) {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine("Invoking index.jsp on " + node);
            stapler.forward(indexJsp, req, rsp);
            return true;
        }
        return false;
    }
}


/*
 * All rights reserved.
 *
 */
package org.kohsuke.stapler.jsp;

import org.kohsuke.stapler.Facet;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.Dispatcher;
import org.kohsuke.stapler.RequestImpl;
import org.kohsuke.stapler.ResponseImpl;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.MetaInfServices;
import org.kohsuke.stapler.lang.Klass;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import java.util.List;
import java.util.logging.Level;
import java.io.IOException;

/**
 * {@link Facet} that adds JSP file support.
 *
 * @author Kohsuke Kawaguchi
 */
@MetaInfServices
public class JSPFacet extends Facet {

    public void buildViewDispatchers(MetaClass owner, List<Dispatcher> dispatchers) {
        dispatchers.add(new Dispatcher() {

            public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException {
                String next = req.tokens.peek();
                if (next == null)
                    return false;
                // only match the end of the URL
                if (req.tokens.countRemainingTokens() > 1)
                    return false;
                // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different
                if (req.getRequestURI().endsWith("/"))
                    return false;
                Stapler stapler = req.getStapler();
                if (!isBasename(next)) {
                    // potentially an attempt to make a folder traversal
                    return false;
                }
                // check static resources
                RequestDispatcher disp = createRequestDispatcher(req, node.getClass(), node, next);
                if (disp == null) {
                    // check JSP views
                    disp = createRequestDispatcher(req, node.getClass(), node, next + ".jsp");
                    if (disp == null)
                        return false;
                }
                req.tokens.next();
                if (traceable())
                    trace(req, rsp, "Invoking " + next + ".jsp" + " on " + node + " for " + req.tokens);
                stapler.forward(disp, req, rsp);
                return true;
            }

            public String toString() {
                return "TOKEN.jsp for url=/TOKEN/...";
            }
        });
    }

    public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException {
        ServletContext context = request.stapler.getServletContext();
        // JSP support is deprecated, and this doesn't work with non-Java objects
        for (Class c = type.toJavaClass(); c != Object.class; c = c.getSuperclass()) {
            String name = "/WEB-INF/side-files/" + c.getName().replace('.', '/').replace('$', '/') + '/' + viewName;
            if (context.getResource(name) != null) {
                // Tomcat returns a RequestDispatcher even if the JSP file doesn't exist.
                // so check if the resource exists first.
                RequestDispatcher disp = context.getRequestDispatcher(name);
                if (disp != null) {
                    return new RequestDispatcherWrapper(disp, it);
                }
            }
        }
        return null;
    }

    public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass nodeMetaClass) throws IOException, ServletException {
        Stapler stapler = req.stapler;
        // TODO: find the list of welcome pages for this class by reading web.xml
        RequestDispatcher indexJsp = createRequestDispatcher(req, node.getClass(), node, "index.jsp");
        if (indexJsp != null) {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine("Invoking index.jsp on " + node);
            stapler.forward(indexJsp, req, rsp)

;
            return true;
        }
        return false;
    }
}


public void setEnd(int end) throws JspTagException

package org.apache.taglibs.standard.tag.rt.core;

import java.util.ArrayList;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.jstl.core.LoopTag;
import javax.servlet.jsp.tagext.IterationTag;
import org.apache.taglibs.standard.tag.common.core.ForEachSupport;

/**
 *
A handler for <forEach> that supports rtexprvalue-based
 * attributes.

 *
 * @author Shawn Bayern
 */
public class ForEachTag extends ForEachSupport implements LoopTag, IterationTag {

    // Accessor methods
    // for tag attribute
    public void setBegin(int begin) throws JspTagException {
        this.beginSpecified = true;
        this.begin = begin;
        validateBegin();
    }

    // for tag attribute

{
        this.endSpecified = true;
        this.end = end;
        validateEnd();
    }

    // for tag attribute
    public void setStep(int step) throws JspTagException {
        this.stepSpecified = true;
        this.step = step;
        validateStep();
    }

    public void setItems(Object o) throws JspTagException {
        // for null items, simulate an empty list
        if (o == null)
            rawItems = new ArrayList();
        else
            rawItems = o;
    }
}


{
        this.beginSpecified = true;
        this.begin = begin;
        validateBegin();
    }

package org.apache.taglibs.standard.tag.rt.core;

import java.util.ArrayList;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.jstl.core.LoopTag;
import javax.servlet.jsp.tagext.IterationTag;
import org.apache.taglibs.standard.tag.common.core.ForEachSupport;

/**
 *
A handler for <forEach> that supports rtexprvalue-based
 * attributes.

 *
 * @author Shawn Bayern
 */
public class ForEachTag extends ForEachSupport implements LoopTag, IterationTag {

    // Accessor methods
    // for tag attribute
    public void setBegin(int begin) throws JspTagException

    // for tag attribute
    public void setEnd(int end) throws JspTagException {
        this.endSpecified = true;
        this.end = end;
        validateEnd();
    }

    // for tag attribute
    public void setStep(int step) throws JspTagException {
        this.stepSpecified = true;
        this.step = step;
        validateStep();
    }

    public void setItems(Object o) throws JspTagException {
        // for null items, simulate an empty list
        if (o == null)
            rawItems = new ArrayList();
        else
            rawItems = o;
    }
}


// for null items, simulate an empty list

package org.apache.taglibs.standard.tag.rt.core;

import java.util.ArrayList;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.jstl.core.LoopTag;
import javax.servlet.jsp.tagext.IterationTag;
import org.apache.taglibs.standard.tag.common.core.ForEachSupport;

/**
 *
A handler for <forEach> that supports rtexprvalue-based
 * attributes.

 *
 * @author Shawn Bayern
 */
public class ForEachTag extends ForEachSupport implements LoopTag, IterationTag {

    // Accessor methods
    // for tag attribute
    public void setBegin(int begin) throws JspTagException {
        this.beginSpecified = true;
        this.begin = begin;
        validateBegin();
    }

    // for tag attribute
    public void setEnd(int end) throws JspTagException {
        this.endSpecified = true;
        this.end = end;
        validateEnd();
    }

    // for tag attribute
    public void setStep(int step) throws JspTagException {
        this.stepSpecified = true;
        this.step = step;
        validateStep();
    }

    public void setItems(Object o) throws JspTagException {

        if (o == null)
            rawItems = new ArrayList();
        else
            rawItems = o;
    }
}


if (o == null)
            rawItems = new ArrayList();
        else
            rawItems = o;

package org.apache.taglibs.standard.tag.rt.core;

import java.util.ArrayList;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.jstl.core.LoopTag;
import javax.servlet.jsp.tagext.IterationTag;
import org.apache.taglibs.standard.tag.common.core.ForEachSupport;

/**
 *
A handler for <forEach> that supports rtexprvalue-based
 * attributes.

 *
 * @author Shawn Bayern
 */
public class ForEachTag extends ForEachSupport implements LoopTag, IterationTag {

    // Accessor methods
    // for tag attribute
    public void setBegin(int begin) throws JspTagException {
        this.beginSpecified = true;
        this.begin = begin;
        validateBegin();
    }

    // for tag attribute
    public void setEnd(int end) throws JspTagException {
        this.endSpecified = true;
        this.end = end;
        validateEnd();
    }

    // for tag attribute
    public void setStep(int step) throws JspTagException {
        this.stepSpecified = true;
        this.step = step;
        validateStep();
    }

    public void setItems(Object o) throws JspTagException {
        // for null items, simulate an empty list


package org.apache.taglibs.standard.tag.rt.core;

import java.util.ArrayList;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.jstl.core.LoopTag;
import javax.servlet.jsp.tagext.IterationTag;
import org.apache.taglibs.standard.tag.common.core.ForEachSupport;

/**
 *
A handler for <forEach> that supports rtexprvalue-based
 * attributes.

 *
 * @author Shawn Bayern
 */
public class ForEachTag extends ForEachSupport implements LoopTag, IterationTag {

    // Accessor methods
    // for tag attribute
    public void setBegin(int begin) throws JspTagException {
        this.beginSpecified = true;
        this.begin = begin;
        validateBegin();
    }

    // for tag attribute
    public void setEnd(int end) throws JspTagException {
        this.endSpecified = true;
        this.end = end;
        validateEnd();
    }

    // for tag attribute
    public void setStep(int step) throws JspTagException {
        this.stepSpecified = true;
        this.step = step;
        validateStep();
    }

    public void setItems(Object o) throws JspTagException {
        // for null items, simulate an empty list
        if (o == null)
            rawItems = new ArrayList();
        else
            rawItems = o;


package org.apache.taglibs.standard.tag.rt.core;

import java.util.ArrayList;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.jstl.core.LoopTag;
import javax.servlet.jsp.tagext.IterationTag;
import org.apache.taglibs.standard.tag.common.core.ForEachSupport;

/**
 *
A handler for <forEach> that supports rtexprvalue-based
 * attributes.

 *
 * @author Shawn Bayern
 */
public class ForEachTag extends ForEachSupport implements LoopTag, IterationTag {

    // Accessor methods
    // for tag attribute
    public void setBegin(int begin) throws JspTagException {
        this.beginSpecified = true;
        this.begin = begin;
        validateBegin();
    }

    // for tag attribute
    public void setEnd(int end) throws JspTagException {
        this.endSpecified = true;
        this.end = e

        validateEnd();
    }

    // for tag attribute
    public void setStep(int step) throws JspTagException {
        this.stepSpecified = true;
        this.step = step;
        validateStep();
    }

    public void setItems(Object o) throws JspTagException {
        // for null items, simulate an empty list
        if (o == null)
            rawItems = new ArrayList();
        else
            rawItems = o;
    }
}


package org.apache.taglibs.standard.tag.rt.core;

import java.util.ArrayList;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.jstl.core.LoopTag;
import javax.servlet.jsp.tagext.IterationTag;
import org.apache.taglibs.standard.tag.common.core.ForEachSupport;

/**
 *
A handler for <forEach> that supports rtexprvalue-based
 * attributes.

 *
 * @author Shawn Bayern
 */
public class ForEachTag extends ForEachSupport implements LoopTag, IterationTag {

    // Accessor methods
    // for tag attribute
    public void setBegin(int begin) throws JspTagException {
        this.beginSpecified = true;
        this.begin = begin;
        validateBegin();
    }

    // for tag attribute
    public void setEnd(int end) throws JspTagException {
        this.endSpecified = true;
        this.end = end;
        validateEnd();
    }

    // for tag attribute
    public void setStep(int step) throws JspTagException {
        this.stepSpecified = true;
        this.step = step;
        validateStep();
    }

    public void set

Items(Object o) throws JspTagException {
        // for null items, simulate an empty list
        if (o == null)
            rawItems = new ArrayList();
        else
            rawItems = o;
    }
}


// Autogenerated from vk-api-schema. Please don't edit it manually.
package com.vk.api.sdk.objects.groups;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.vk.api.sdk.objects.Validable;
import java.util.Objects;

/**
 * CountersGroup object
 */
public class CountersGroup implements Validable {

    /**
     * Addresses number
     */
    @SerializedName("addresses")
    private Integer addresses;

    /**
     * Photo albums number
     */
    @SerializedName("albums")
    private Integer albums;

    /**
     * Audios number
     */
    @SerializedName("audios")
    private Integer audios;

    /**
     * Audio playlists number
     */
    @SerializedName("audio_playlists")
    private Integer audioPlaylists;

    /**
     * Docs number
     */
    @SerializedName("docs")
    private Integer docs;

    /**
     * Market items number
     */
    @SerializedName("market")
    private Integer market;

    /**
     * Photos number
     */
    @SerializedName("photos")
    private Integer photos;

    /**
     * Topics number
     */
    @SerializedName("topics")
    private Integer topics;

    /**
     * Videos number
     */
    @SerializedName("videos")
    private Integer videos;

    /**
     * Market services number
     */
    @SerializedName("market_services")
    private Integer marketServices;

    /**
     * Podcasts number
     */
    @SerializedName("podcasts")
    private Integer podcasts;

    /**
     * Articles number
     */
    @SerializedName("articles")
    private Integer articles;

    /**
     * Narratives number
     */
    @SerializedName("narratives")
    private Integer narratives;

    /**
     * Clips number
     */
    @SerializedName("clips")
    private Integer clips;

    /**
     * Clips followers number
     */
    @SerializedName("clips_followers")
    private Integer clipsFollowers;

    public Integer getAddresses() {
        return addresses;
    }

    public CountersGroup setAddresses(Integer addresses) {
        this.addresses = addresses;
        return this;
    }

    public Integer getAlbums() {
        return albums;
    }

    public CountersGroup setAlbums(Integer albums) {
        this.albums = albums;
        return this;
    }

    public Integer getAudios() {
        return audios;
    }

    public CountersGroup setAudios(Integer audios) {
        this.audios = audios;
        return this;
    }

    public Integer getAudioPlaylists() {
        return audioPlaylists;
    }

    public CountersGroup setAudioPlaylists(Integer audioPlaylists) {
        this.audioPlaylists = audioPlaylists;
        return this;
    }

    public Integer getDocs() {
        return docs;
    }

    public CountersGroup setDocs(Integer docs) {
        this.docs = docs;
        return this;
    }

    public Integer getMarket() {
        return market;
    }

    public CountersGroup setMarket(Integer market) {
        this.market = market;
        return this;
    }

    public Integer getPhotos() {
        return photos;
    }

    public CountersGroup setPhotos(Integer photos) {
        this.photos = photos;
        return this;
    }

    public Integer getTopics() {
        return topics;
    }

    public CountersGroup setTopics(Integer topics) {
        this.topics = topics;
        return this;
    }

{
        return videos;
    }

    public CountersGroup setVideos(Integer videos) {
        this.videos = videos;
        return this;
    }

    public Integer getMarketServices() {
        return marketServices;
    }

    public CountersGroup setMarketServices(Integer marketServices) {
        this.marketServices = marketServices;
        return this;
    }

    public Integer getPodcasts() {
        return podcasts;
    }

    public CountersGroup setPodcasts(Integer podcasts) {
        this.podcasts = podcasts;
        return this;
    }

    public Integer getArticles() {
        return articles;
    }

    public CountersGroup setArticles(Integer articles) {
        this.articles = articles;
        return this;
    }

    public Integer getNarratives() {
        return narratives;
    }

    public CountersGroup setNarratives(Integer narratives) {
        this.narratives = narratives;
        return this;
    }

    public Integer getClips() {
        return clips;
    }

    public CountersGroup setClips(Integer clips) {
        this.clips = clips;
        return this;
    }

    public Integer getClipsFollowers() {
        return clipsFollowers;
    }

    public CountersGroup setClipsFollowers(Integer clipsFollowers) {
        this.clipsFollowers = clipsFollowers;
        return this;
    }

    @Override
    public int hashCode() {
        return Objects.hash(addresses, albums, narratives, topics, clips, marketServices, videos, photos, market, podcasts, docs, audios, audioPlaylists, articles, clipsFollowers);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        CountersGroup countersGroup = (CountersGroup) o;
        return Objects.equals(addresses, countersGroup.addresses) && Objects.equals(albums, countersGroup.albums) && Objects.equals(narratives, countersGroup.narratives) && Objects.equals(topics, countersGroup.topics) && Objects.equals(clips, countersGroup.clips) && Objects.equals(audioPlaylists, countersGroup.audioPlaylists) && Objects.equals(videos, countersGroup.videos) && Objects.equals(marketServices, countersGroup.marketServices) && Objects.equals(photos, countersGroup.photos) && Objects.equals(market, countersGroup.market) && Objects.equals(podcasts, countersGroup.podcasts) && Objects.equals(docs, countersGroup.docs) && Objects.equals(audios, countersGroup.audios) && Objects.equals(clipsFollowers, countersGroup.clipsFollowers) && Objects.equals(articles, countersGroup.articles);
    }

    @Override
    public String toString() {
        final Gson gson = new Gson();
        return gson.toJson(this);
    }

    public String toPrettyString() {
        final StringBuilder sb = new StringBuilder("CountersGroup{");
        sb.append("addresses=").append(addresses);
        sb.append(", albums=").append(albums);
        sb.append(", narratives=").append(narratives);
        sb.append(", topics=").append(topics);
        sb.append(", clips=").append(clips);
        sb.append(", audioPlaylists=").append(audioPlaylists);
        sb.append(", videos=").append(videos);
        sb.append(", marketServices=").append(marketServices);
        sb.append(", photos=").append(photos);
        sb.append(", market=").append(market);
        sb.append(", podcasts=").append(podcasts);
        sb.append(", docs=").append(docs);
        sb.append(", audios=").append(audios);
        sb.append(", clipsFollowers=").append(clipsFollowers);
        sb.append(", articles=").append(articles);
        sb.append('}');
        return sb.toString();
    }
}


// Autogenerated from vk-api-schema. Please don't edit it manually.
package com.vk.api.sdk.objects.groups;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.vk.api.sdk.objects.Validable;
import java.util.Objects;

/**
 * CountersGroup object
 */
public class CountersGroup implements Validable {

    /**
     * Addresses number
     */
    @SerializedName("addresses")
    private Integer addresses;

    /**
     * Photo albums number
     */
    @SerializedName("albums")
    private Integer albums;

    /**
     * Audios number
     */
    @SerializedName("audios")
    private Integer audios;

    /**
     * Audio playlists number
     */
    @SerializedName("audio_playlists")
    private Integer audioPlaylists;

    /**
     * Docs number
     */
    @SerializedName("docs")
    private Integer docs;

    /**
     * Market items number
     */
    @SerializedName("market")
    private Integer market;

    /**
     * Photos number
     */
    @SerializedName("photos")
    private Integer photos;

    /**
     * Topics number
     */
    @SerializedName("topics")
    private Integer topics;

    /**
     * Videos number
     */
    @SerializedName("videos")
    private Integer videos;

    /**
     * Market services number
     */
    @SerializedName("market_services")
    private Integer marketServices;

    /**
     * Podcasts number
     */
    @SerializedName("podcasts")
    private Integer podcasts;

    /**
     * Articles number
     */
    @SerializedName("articles")
    private Integer articles;

    /**
     * Narratives number
     */
    @SerializedName("narratives")
    private Integer narratives;

    /**
     * Clips number
     */
    @SerializedName("clips")
    private Integer clips;

    /**
     * Clips followers number
     */
    @SerializedName("clips_followers")
    private Integer clipsFollowers;

    public Integer getAddresses() {
        return addresses;
    }

    public CountersGroup setAddresses(Integer addresses) {
        this.addresses = addresses;
        return this;
    }

    public Integer getAlbums() {
        return albums;
    }

    public CountersGroup setAlbums(Integer albums) {
        this.albums = albums;
        return this;
    }

    public Integer getAudios() {
        return audios;
    }

    public CountersGroup setAudios(Integer audios) {
        this.audios = audios;
        return this;
    }

    public Integer getAudioPlaylists() {
        return audioPlaylists;
    }

    public CountersGroup setAudioPlaylists(Integer audioPlaylists) {
        this.audioPlaylists = audioPlaylists;
        return this;
    }

    public Integer getDocs() {
        return docs;
    }

    public CountersGroup setDocs(Integer docs) {
        this.docs = docs;
        return this;
    }

    public Integer getMarket() {
        return market;
    }

    public CountersGroup setMarket(Integer market) {
        this.market = market;
        return this;
    }

    public Integer getPhotos() {
        return photos;
    }

    public CountersGroup setPhotos(Integer photos) {
        this.photos = photos;
        return this;
    }

    public Integer getTopics() {
        return topics;
    }

    public CountersGroup setTopics(Integer topics) {
        this.topics = topics;
        return this;
    }

    public Integer getVideos() {
        return videos;
    }

    public CountersGroup setVideos(Integer videos) {
        this.videos = videos;
        return this;
    }

    public Integer getMarketServices() {
        return marketServices;
    }

    public CountersGroup setMarketServices(Integer marketServices) {
        this.marketServices = marketServices;
        return this;
    }

    public Integer getPodcasts() {
        return podcasts;
    }

    public CountersGroup setPodcasts(Integer podcasts) {
        this.podcasts = podcasts;
        return this;
    }

    public Integer getArticles() {
        return articles;
    }

    public CountersGroup setArticles(Integer articles) {
        this.articles = articles;
        return this;
    }

    public Integer getNarratives() {
        return narratives;
    }

    public CountersGroup setNarratives(Integer narratives) {
        this.narratives = narratives;
        return this;
    }

    public Integer getClips()

    public CountersGroup setClips(Integer clips) {
        this.clips = clips;
        return this;
    }

    public Integer getClipsFollowers() {
        return clipsFollowers;
    }

    public CountersGroup setClipsFollowers(Integer clipsFollowers) {
        this.clipsFollowers = clipsFollowers;
        return this;
    }

    @Override
    public int hashCode() {
        return Objects.hash(addresses, albums, narratives, topics, clips, marketServices, videos, photos, market, podcasts, docs, audios, audioPlaylists, articles, clipsFollowers);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        CountersGroup countersGroup = (CountersGroup) o;
        return Objects.equals(addresses, countersGroup.addresses) && Objects.equals(albums, countersGroup.albums) && Objects.equals(narratives, countersGroup.narratives) && Objects.equals(topics, countersGroup.topics) && Objects.equals(clips, countersGroup.clips) && Objects.equals(audioPlaylists, countersGroup.audioPlaylists) && Objects.equals(videos, countersGroup.videos) && Objects.equals(marketServices, countersGroup.marketServices) && Objects.equals(photos, countersGroup.photos) && Objects.equals(market, countersGroup.market) && Objects.equals(podcasts, countersGroup.podcasts) && Objects.equals(docs, countersGroup.docs) && Objects.equals(audios, countersGroup.audios) && Objects.equals(clipsFollowers, countersGroup.clipsFollowers) && Objects.equals(articles, countersGroup.articles);
    }

    @Override
    public String toString() {
        final Gson gson = new Gson();
        return gson.toJson(this);
    }

    public String toPrettyString() {
        final StringBuilder sb = new StringBuilder("CountersGroup{");
        sb.append("addresses=").append(addresses);
        sb.append(", albums=").append(albums);
        sb.append(", narratives=").append(narratives);
        sb.append(", topics=").append(topics);
        sb.append(", clips=").append(clips);
        sb.append(", audioPlaylists=").append(audioPlaylists);
        sb.append(", videos=").append(videos);
        sb.append(", marketServices=").append(marketServices);
        sb.append(", photos=").append(photos);
        sb.append(", market=").append(market);
        sb.append(", podcasts=").append(podcasts);
        sb.append(", docs=").append(docs);
        sb.append(", audios=").append(audios);
        sb.append(", clipsFollowers=").append(clipsFollowers);
        sb.append(", articles=").append(articles);
        sb.append('}');
        return sb.toString();
    }
}


        if (this == o)
            return true;

// Autogenerated from vk-api-schema. Please don't edit it manually.
package com.vk.api.sdk.objects.groups;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.vk.api.sdk.objects.Validable;
import java.util.Objects;

/**
 * CountersGroup object
 */
public class CountersGroup implements Validable {

    /**
     * Addresses number
     */
    @SerializedName("addresses")
    private Integer addresses;

    /**
     * Photo albums number
     */
    @SerializedName("albums")
    private Integer albums;

    /**
     * Audios number
     */
    @SerializedName("audios")
    private Integer audios;

    /**
     * Audio playlists number
     */
    @SerializedName("audio_playlists")
    private Integer audioPlaylists;

    /**
     * Docs number
     */
    @SerializedName("docs")
    private Integer docs;

    /**
     * Market items number
     */
    @SerializedName("market")
    private Integer market;

    /**
     * Photos number
     */
    @SerializedName("photos")
    private Integer photos;

    /**
     * Topics number
     */
    @SerializedName("topics")
    private Integer topics;

    /**
     * Videos number
     */
    @SerializedName("videos")
    private Integer videos;

    /**
     * Market services number
     */
    @SerializedName("market_services")
    private Integer marketServices;

    /**
     * Podcasts number
     */
    @SerializedName("podcasts")
    private Integer podcasts;

    /**
     * Articles number
     */
    @SerializedName("articles")
    private Integer articles;

    /**
     * Narratives number
     */
    @SerializedName("narratives")
    private Integer narratives;

    /**
     * Clips number
     */
    @SerializedName("clips")
    private Integer clips;

    /**
     * Clips followers number
     */
    @SerializedName("clips_followers")
    private Integer clipsFollowers;

    public Integer getAddresses() {
        return addresses;
    }

    public CountersGroup setAddresses(Integer addresses) {
        this.addresses = addresses;
        return this;
    }

    public Integer getAlbums() {
        return albums;
    }

    public CountersGroup setAlbums(Integer albums) {
        this.albums = albums;
        return this;
    }

    public Integer getAudios() {
        return audios;
    }

    public CountersGroup setAudios(Integer audios) {
        this.audios = audios;
        return this;
    }

    public Integer getAudioPlaylists() {
        return audioPlaylists;
    }

    public CountersGroup setAudioPlaylists(Integer audioPlaylists) {
        this.audioPlaylists = audioPlaylists;
        return this;
    }

    public Integer getDocs() {
        return docs;
    }

    public CountersGroup setDocs(Integer docs) {
        this.docs = docs;
        return this;
    }

    public Integer getMarket() {
        return market;
    }

    public CountersGroup setMarket(Integer market) {
        this.market = market;
        return this;
    }

    public Integer getPhotos() {
        return photos;
    }

    public CountersGroup setPhotos(Integer photos) {
        this.photos = photos;
        return this;
    }

    public Integer getTopics() {
        return topics;
    }

    public CountersGroup setTopics(Integer topics) {
        this.topics = topics;
        return this;
    }

    public Integer getVideos() {
        return videos;
    }

    public CountersGroup setVideos(Integer videos) {
        this.videos = videos;
        return this;
    }

    public Integer getMarketServices() {
        return marketServices;
    }

    public CountersGroup setMarketServices(Integer marketServices) {
        this.marketServices = marketServices;
        return this;
    }

    public Integer getPodcasts() {
        return podcasts;
    }

    public CountersGroup setPodcasts(Integer podcasts) {
        this.podcasts = podcasts;
        return this;
    }

    public Integer getArticles() {
        return articles;
    }

    public CountersGroup setArticles(Integer articles) {
        this.articles = articles;
        return this;
    }

    public Integer getNarratives() {
        return narratives;
    }

    public CountersGroup setNarratives(Integer narratives) {
        this.narratives = narratives;
        return this;
    }

    public Integer getClips() {
        return clips;
    }

    public CountersGroup setClips(Integer clips) {
        this.clips = clips;
        return this;
    }

    public Integer getClipsFollowers() {
        return clipsFollowers;
    }

    public CountersGroup setClipsFollowers(Integer clipsFollowers) {
        this.clipsFollowers = clipsFollowers;
        return this;
    }

    @Override
    public int hashCode() {
        return Objects.hash(addresses, albums, narratives, topics, clips, marketServices, videos, photos, market, podcasts, docs, audios, audioPlaylists, articles, clipsFollowers);
    }

    @Override
    public boolean equals(Object o) {

        if (o == null || getClass() != o.getClass())
            return false;
        CountersGroup countersGroup = (CountersGroup) o;
        return Objects.equals(addresses, countersGroup.addresses) && Objects.equals(albums, countersGroup.albums) && Objects.equals(narratives, countersGroup.narratives) && Objects.equals(topics, countersGroup.topics) && Objects.equals(clips, countersGroup.clips) && Objects.equals(audioPlaylists, countersGroup.audioPlaylists) && Objects.equals(videos, countersGroup.videos) && Objects.equals(marketServices, countersGroup.marketServices) && Objects.equals(photos, countersGroup.photos) && Objects.equals(market, countersGroup.market) && Objects.equals(podcasts, countersGroup.podcasts) && Objects.equals(docs, countersGroup.docs) && Objects.equals(audios, countersGroup.audios) && Objects.equals(clipsFollowers, countersGroup.clipsFollowers) && Objects.equals(articles, countersGroup.articles);
    }

    @Override
    public String toString() {
        final Gson gson = new Gson();
        return gson.toJson(this);
    }

    public String toPrettyString() {
        final StringBuilder sb = new StringBuilder("CountersGroup{");
        sb.append("addresses=").append(addresses);
        sb.append(", albums=").append(albums);
        sb.append(", narratives=").append(narratives);
        sb.append(", topics=").append(topics);
        sb.append(", clips=").append(clips);
        sb.append(", audioPlaylists=").append(audioPlaylists);
        sb.append(", videos=").append(videos);
        sb.append(", marketServices=").append(marketServices);
        sb.append(", photos=").append(photos);
        sb.append(", market=").append(market);
        sb.append(", podcasts=").append(podcasts);
        sb.append(", docs=").append(docs);
        sb.append(", audios=").append(audios);
        sb.append(", clipsFollowers=").append(clipsFollowers);
        sb.append(", articles=").append(articles);
        sb.append('}');
        return sb.toString();
    }
}


if (o == null || getClass() != o.getClass())
            return false;
        CountersGroup countersGroup = (CountersGroup) o;

// Autogenerated from vk-api-schema. Please don't edit it manually.
package com.vk.api.sdk.objects.groups;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.vk.api.sdk.objects.Validable;
import java.util.Objects;

/**
 * CountersGroup object
 */
public class CountersGroup implements Validable {

    /**
     * Addresses number
     */
    @SerializedName("addresses")
    private Integer addresses;

    /**
     * Photo albums number
     */
    @SerializedName("albums")
    private Integer albums;

    /**
     * Audios number
     */
    @SerializedName("audios")
    private Integer audios;

    /**
     * Audio playlists number
     */
    @SerializedName("audio_playlists")
    private Integer audioPlaylists;

    /**
     * Docs number
     */
    @SerializedName("docs")
    private Integer docs;

    /**
     * Market items number
     */
    @SerializedName("market")
    private Integer market;

    /**
     * Photos number
     */
    @SerializedName("photos")
    private Integer photos;

    /**
     * Topics number
     */
    @SerializedName("topics")
    private Integer topics;

    /**
     * Videos number
     */
    @SerializedName("videos")
    private Integer videos;

    /**
     * Market services number
     */
    @SerializedName("market_services")
    private Integer marketServices;

    /**
     * Podcasts number
     */
    @SerializedName("podcasts")
    private Integer podcasts;

    /**
     * Articles number
     */
    @SerializedName("articles")
    private Integer articles;

    /**
     * Narratives number
     */
    @SerializedName("narratives")
    private Integer narratives;

    /**
     * Clips number
     */
    @SerializedName("clips")
    private Integer clips;

    /**
     * Clips followers number
     */
    @SerializedName("clips_followers")
    private Integer clipsFollowers;

    public Integer getAddresses() {
        return addresses;
    }

    public CountersGroup setAddresses(Integer addresses) {
        this.addresses = addresses;
        return this;
    }

    public Integer getAlbums() {
        return albums;
    }

    public CountersGroup setAlbums(Integer albums) {
        this.albums = albums;
        return this;
    }

    public Integer getAudios() {
        return audios;
    }

    public CountersGroup setAudios(Integer audios) {
        this.audios = audios;
        return this;
    }

    public Integer getAudioPlaylists() {
        return audioPlaylists;
    }

    public CountersGroup setAudioPlaylists(Integer audioPlaylists) {
        this.audioPlaylists = audioPlaylists;
        return this;
    }

    public Integer getDocs() {
        return docs;
    }

    public CountersGroup setDocs(Integer docs) {
        this.docs = docs;
        return this;
    }

    public Integer getMarket() {
        return market;
    }

    public CountersGroup setMarket(Integer market) {
        this.market = market;
        return this;
    }

    public Integer getPhotos() {
        return photos;
    }

    public CountersGroup setPhotos(Integer photos) {
        this.photos = photos;
        return this;
    }

    public Integer getTopics() {
        return topics;
    }

    public CountersGroup setTopics(Integer topics) {
        this.topics = topics;
        return this;
    }

    public Integer getVideos() {
        return videos;
    }

    public CountersGroup setVideos(Integer videos) {
        this.videos = videos;
        return this;
    }

    public Integer getMarketServices() {
        return marketServices;
    }

    public CountersGroup setMarketServices(Integer marketServices) {
        this.marketServices = marketServices;
        return this;
    }

    public Integer getPodcasts() {
        return podcasts;
    }

    public CountersGroup setPodcasts(Integer podcasts) {
        this.podcasts = podcasts;
        return this;
    }

    public Integer getArticles() {
        return articles;
    }

    public CountersGroup setArticles(Integer articles) {
        this.articles = articles;
        return this;
    }

    public Integer getNarratives() {
        return narratives;
    }

    public CountersGroup setNarratives(Integer narratives) {
        this.narratives = narratives;
        return this;
    }

    public Integer getClips() {
        return clips;
    }

    public CountersGroup setClips(Integer clips) {
        this.clips = clips;
        return this;
    }

    public Integer getClipsFollowers() {
        return clipsFollowers;
    }

    public CountersGroup setClipsFollowers(Integer clipsFollowers) {
        this.clipsFollowers = clipsFollowers;
        return this;
    }

    @Override
    public int hashCode() {
        return Objects.hash(addresses, albums, narratives, topics, clips, marketServices, videos, photos, market, podcasts, docs, audios, audioPlaylists, articles, clipsFollowers);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;

        return Objects.equals(addresses, countersGroup.addresses) && Objects.equals(albums, countersGroup.albums) && Objects.equals(narratives, countersGroup.narratives) && Objects.equals(topics, countersGroup.topics) && Objects.equals(clips, countersGroup.clips) && Objects.equals(audioPlaylists, countersGroup.audioPlaylists) && Objects.equals(videos, countersGroup.videos) && Objects.equals(marketServices, countersGroup.marketServices) && Objects.equals(photos, countersGroup.photos) && Objects.equals(market, countersGroup.market) && Objects.equals(podcasts, countersGroup.podcasts) && Objects.equals(docs, countersGroup.docs) && Objects.equals(audios, countersGroup.audios) && Objects.equals(clipsFollowers, countersGroup.clipsFollowers) && Objects.equals(articles, countersGroup.articles);
    }

    @Override
    public String toString() {
        final Gson gson = new Gson();
        return gson.toJson(this);
    }

    public String toPrettyString() {
        final StringBuilder sb = new StringBuilder("CountersGroup{");
        sb.append("addresses=").append(addresses);
        sb.append(", albums=").append(albums);
        sb.append(", narratives=").append(narratives);
        sb.append(", topics=").append(topics);
        sb.append(", clips=").append(clips);
        sb.append(", audioPlaylists=").append(audioPlaylists);
        sb.append(", videos=").append(videos);
        sb.append(", marketServices=").append(marketServices);
        sb.append(", photos=").append(photos);
        sb.append(", market=").append(market);
        sb.append(", podcasts=").append(podcasts);
        sb.append(", docs=").append(docs);
        sb.append(", audios=").append(audios);
        sb.append(", clipsFollowers=").append(clipsFollowers);
        sb.append(", articles=").append(articles);
        sb.append('}');
        return sb.toString();
    }
}


return Objects.equals(addresses, countersGroup.addresses) && Objects.equals(albums, countersGroup.albums) && Objects.equals(narratives, countersGroup.narratives) && Objects.equals(topics, countersGroup.topics) && Objects.equals(clips, countersGroup.clips) && Objects.equals(audioPlaylists, countersGroup.audioPlaylists) && Objects.equals(videos, countersGroup.videos) && Objects.equals(marketServices, countersGroup.marketServices) && Objects.equals(photos, countersGroup.photos) && Objects.equals(market, countersGroup.market) && Objects.equals(podcasts, countersGroup.podcasts) && Objects.equals(docs, countersGroup.docs) && Objects.equals(audios, countersGroup.audios) && Objects.equals(clipsFollowers, countersGroup.clipsFollowers) && Objects.equals(articles, countersGroup.articles);
    }

// Autogenerated from vk-api-schema. Please don't edit it manually.
package com.vk.api.sdk.objects.groups;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.vk.api.sdk.objects.Validable;
import java.util.Objects;

/**
 * CountersGroup object
 */
public class CountersGroup implements Validable {

    /**
     * Addresses number
     */
    @SerializedName("addresses")
    private Integer addresses;

    /**
     * Photo albums number
     */
    @SerializedName("albums")
    private Integer albums;

    /**
     * Audios number
     */
    @SerializedName("audios")
    private Integer audios;

    /**
     * Audio playlists number
     */
    @SerializedName("audio_playlists")
    private Integer audioPlaylists;

    /**
     * Docs number
     */
    @SerializedName("docs")
    private Integer docs;

    /**
     * Market items number
     */
    @SerializedName("market")
    private Integer market;

    /**
     * Photos number
     */
    @SerializedName("photos")
    private Integer photos;

    /**
     * Topics number
     */
    @SerializedName("topics")
    private Integer topics;

    /**
     * Videos number
     */
    @SerializedName("videos")
    private Integer videos;

    /**
     * Market services number
     */
    @SerializedName("market_services")
    private Integer marketServices;

    /**
     * Podcasts number
     */
    @SerializedName("podcasts")
    private Integer podcasts;

    /**
     * Articles number
     */
    @SerializedName("articles")
    private Integer articles;

    /**
     * Narratives number
     */
    @SerializedName("narratives")
    private Integer narratives;

    /**
     * Clips number
     */
    @SerializedName("clips")
    private Integer clips;

    /**
     * Clips followers number
     */
    @SerializedName("clips_followers")
    private Integer clipsFollowers;

    public Integer getAddresses() {
        return addresses;
    }

    public CountersGroup setAddresses(Integer addresses) {
        this.addresses = addresses;
        return this;
    }

    public Integer getAlbums() {
        return albums;
    }

    public CountersGroup setAlbums(Integer albums) {
        this.albums = albums;
        return this;
    }

    public Integer getAudios() {
        return audios;
    }

    public CountersGroup setAudios(Integer audios) {
        this.audios = audios;
        return this;
    }

    public Integer getAudioPlaylists() {
        return audioPlaylists;
    }

    public CountersGroup setAudioPlaylists(Integer audioPlaylists) {
        this.audioPlaylists = audioPlaylists;
        return this;
    }

    public Integer getDocs() {
        return docs;
    }

    public CountersGroup setDocs(Integer docs) {
        this.docs = docs;
        return this;
    }

    public Integer getMarket() {
        return market;
    }

    public CountersGroup setMarket(Integer market) {
        this.market = market;
        return this;
    }

    public Integer getPhotos() {
        return photos;
    }

    public CountersGroup setPhotos(Integer photos) {
        this.photos = photos;
        return this;
    }

    public Integer getTopics() {
        return topics;
    }

    public CountersGroup setTopics(Integer topics) {
        this.topics = topics;
        return this;
    }

    public Integer getVideos() {
        return videos;
    }

    public CountersGroup setVideos(Integer videos) {
        this.videos = videos;
        return this;
    }

    public Integer getMarketServices() {
        return marketServices;
    }

    public CountersGroup setMarketServices(Integer marketServices) {
        this.marketServices = marketServices;
        return this;
    }

    public Integer getPodcasts() {
        return podcasts;
    }

    public CountersGroup setPodcasts(Integer podcasts) {
        this.podcasts = podcasts;
        return this;
    }

    public Integer getArticles() {
        return articles;
    }

    public CountersGroup setArticles(Integer articles) {
        this.articles = articles;
        return this;
    }

    public Integer getNarratives() {
        return narratives;
    }

    public CountersGroup setNarratives(Integer narratives) {
        this.narratives = narratives;
        return this;
    }

    public Integer getClips() {
        return clips;
    }

    public CountersGroup setClips(Integer clips) {
        this.clips = clips;
        return this;
    }

    public Integer getClipsFollowers() {
        return clipsFollowers;
    }

    public CountersGroup setClipsFollowers(Integer clipsFollowers) {
        this.clipsFollowers = clipsFollowers;
        return this;
    }

    @Override
    public int hashCode() {
        return Objects.hash(addresses, albums, narratives, topics, clips, marketServices, videos, photos, market, podcasts, docs, audios, audioPlaylists, articles, clipsFollowers);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        CountersGroup countersGroup = (CountersGroup) o;

    @Override
    public String toString() {
        final Gson gson = new Gson();
        return gson.toJson(this);
    }

    public String toPrettyString() {
        final StringBuilder sb = new StringBuilder("CountersGroup{");
        sb.append("addresses=").append(addresses);
        sb.append(", albums=").append(albums);
        sb.append(", narratives=").append(narratives);
        sb.append(", topics=").append(topics);
        sb.append(", clips=").append(clips);
        sb.append(", audioPlaylists=").append(audioPlaylists);
        sb.append(", videos=").append(videos);
        sb.append(", marketServices=").append(marketServices);
        sb.append(", photos=").append(photos);
        sb.append(", market=").append(market);
        sb.append(", podcasts=").append(podcasts);
        sb.append(", docs=").append(docs);
        sb.append(", audios=").append(audios);
        sb.append(", clipsFollowers=").append(clipsFollowers);
        sb.append(", articles=").append(articles);
        sb.append('}');
        return sb.toString();
    }
}


// Autogenerated from vk-api-schema. Please don't edit it manually.
package com.vk.api.sdk.objects.groups;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.vk.api.sdk.objects.Validable;
import java.util.Objects;

/**
 * CountersGroup object
 */
public class CountersGroup implements Validable {

    /**
     * Addresses number
     */
    @SerializedName("addresses")
    private Integer addresses;

    /**
     * Photo albums number
     */
    @SerializedName("albums")
    private Integer albums;

    /**
     * Audios number
     */
    @SerializedName("audios")
    private Integer audios;

    /**
     * Audio playlists number
     */
    @SerializedName("audio_playlists")
    private Integer audioPlaylists;

    /**
     * Docs number
     */
    @SerializedName("docs")
    private Integer docs;

    /**
     * Market items number
     */
    @SerializedName("market")
    private Integer market;

    /**
     * Photos number
     */
    @SerializedName("photos")
    private Integer photos;

    /**
     * Topics number
     */
    @SerializedName("topics")
    private Integer topics;

    /**
     * Videos number
     */
    @SerializedName("videos")
    private Integer videos;

    /**
     * Market services number
     */
    @SerializedName("market_services")
    private Integer marketServices;

    /**
     * Podcasts number
     */
    @SerializedName("podcasts")
    private Integer podcasts;

    /**
     * Articles number
     */
    @SerializedName("articles")
    private Integer articles;

    /**
     * Narratives number
     */
    @SerializedName("narratives")
    private Integer narratives;

    /**
     * Clips number
     */
    @SerializedName("clips")
    private Integer clips;

    /**
     * Clips followers number
     */
    @SerializedName("clips_followers")
    private Integer clipsFollowers;

    public Integer getAddresses() {
        return addresses;
    }

    public CountersGroup setAddresses(Integer addresses) {
        this.addresses = addresses;
        return this;
    }

    public Integer getAlbums() {
        return albums;
    }

    public CountersGroup setAlbums(Integer albums) {
        this.albums = albums;
        return this;
    }

    public Integer getAudios() {
        return audios;
    }

    public CountersGroup setAudios(Integer audios) {
        this.audios = audios;
        return this;
    }

    public Integer getAudioPlaylists() {
        return audioPlaylists;
    }

    public CountersGroup setAudioPlaylists(Integer audioPlaylists) {
        this.audioPlaylists = audioPlaylists;
        return this;
    }

    public Integer getDocs() {
        return docs;
    }

    public CountersGroup setDocs(Integer docs) {
        this.docs = docs;
        return this;
    }

    public Integer getMarket() {
        return market;
    }

    public CountersGroup setMarket(Integer market) {
        this.market = market;
        return this;
    }

    public Integer getPhotos() {
        return photos;
    }

    public CountersGroup setPhotos(Integer photos) {
        this.photos = photos;
        return this;
    }

    public Integer getTopics() {
        return topics;
    }

    public CountersGroup setTopics(Integer topics) {
        this.topics = topics;
        return this;
    }

    public Integer getVideos() {
        return videos;
    }

    public CountersGroup setVideos(Integer videos) {
        this.videos = videos;
        return this;
    }

    public Integer getMarketServices() {
        return marketServices;
    }

    public CountersGroup setMarketServices(Integer marketServices) {
        this.marketServices = marketServices;
        return this;
    }

    public Integer getPodcasts() {
        return podcasts;
    }

    public CountersGroup setPodcasts(Integer podcasts) {
        this.podcasts = podcasts;
        return this;
    }

    public Integer getArticles() {
        return articles;
    }

    public CountersGroup setArticles(Integer articles) {
        this.articles = articles;
        return this;
    }

    public Integer getNarratives() {
        return narratives;
    }

    public CountersGroup setNarratives(Integer narratives) {
        this.narratives = narratives;
        return this;
    }

    public Integer getClips() {
        return clips;
    }

    public CountersGroup setClips(Integer clips) {
        this.clips = clips;
        return this;
    }

    public Integer getClipsFollowers() {
        return clipsFollowers;
    }

    public CountersGroup setClipsFollowers(Integer clipsFollowers) {
        this.clipsFollowers = clipsFollowers;
        return this;
    }

    @Override
    public int hashCode() {
        return Objects.hash(addresses, albums, narratives, topics, clips, marketServices, videos, photos, market, podcasts, docs, audios, audioPlaylists, articles, clipsFollowers);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        CountersGroup countersGroup = (CountersGroup) o;
        return Objects.equals(addresses, countersGroup.addresses) && Objects.equals(albums, countersGroup.albums) && Objects.equals(narratives, countersGroup.narratives) && Objects.equals(topics, countersGroup.topics) && Objects.equals(clips, countersGroup.clips) && Objects.equals(audioPlaylists, countersGroup.audioPlaylists) && Objects.equals(videos, countersGroup.videos) && Objects.equals(marketServices, countersGroup.marketServices) && Objects.equals(photos, countersGroup.photos) && Objects.equals(market, countersGroup.market) && Objects.equals(podcasts, countersGroup.podcasts) && Objects.equals(docs, countersGroup.docs) && Objects.equals(audios, countersGroup.audios) && Objects.equals(clipsFollowers, countersGroup.clipsFollowers) && Objects.equals(articles, countersGroup.articles);
    }

    @Override
    public String toString() {
        final Gson gson = new Gson();
        return gson.toJson(this);
    }

    public String toPrettyString() {
        final StringBuilder sb = new StringBuilder("CountersGroup{");
        sb.append("addresses=").append(addresses);
        sb.append(", albums=").append(albums);
        sb.append(", narratives=").append(narratives);
        sb.append(", topics=").append(topics);
        sb.append(", clips=").append(clips);
        sb.append(", audioPlaylists=").append(audioPlaylists);
        sb.append(", videos=").append(videos);
        sb.append(", marketServices=").append(marketServices);
        sb.append(", photos=").append(ph

        sb.append(", market=").append(market);
        sb.append(", podcasts=").append(podcasts);
        sb.append(", docs=").append(docs);
        sb.append(", audios=").append(audios);
        sb.append(", clipsFollowers=").append(clipsFollowers);
        sb.append(", articles=").append(articles);
        sb.append('}');
        return sb.toString();
    }
}


if (o == null || getClass() != o.getClass())
            return false;

        CountersGroup countersGroup = (CountersGroup) o;
        return Objects.equals(addresses, countersGroup.addresses) && Objects.equals(albums, countersGroup.albums) && Objects.equals(narratives, countersGroup.narratives) && Objects.equals(topics, countersGroup.topics) && Objects.equals(clips, countersGroup.clips) && Objects.equals(audioPlaylists, countersGroup.audioPlaylists) && Objects.equals(videos, countersGroup.videos) && Objects.equals(marketServices, countersGroup.marketServices) && Objects.equals(photos, countersGroup.photos) && Objects.equals(market, countersGroup.market) && Objects.equals(podcasts, countersGroup.podcasts) && Objects.equals(docs, countersGroup.docs) && Objects.equals(audios, countersGroup.audios) && Objects.equals(clipsFollowers, countersGroup.clipsFollowers) && Objects.equals(articles, countersGroup.articles);
    }

    @Override
    public String toString() {
        final Gson gson = new Gson();
        return gson.toJson(this);
    }

    public String toPrettyString() {
        final StringBuilder sb = new StringBuilder("CountersGroup{");
        sb.append("addresses=").append(addresses);
        sb.append(", albums=").append(albums);
        sb.append(", narratives=").append(narratives);
        sb.append(", topics=").append(topics);
        sb.append(", clips=").append(clips);
        sb.append(", audioPlaylists=").append(audioPlaylists);
        sb.append(", videos=").append(videos);
        sb.append(", marketServices=").append(marketServices);
        sb.append(", photos=").append(photos);
        sb.append(", market=").append(market);
        sb.append(", podcasts=").append(podcasts);
        sb.append(", docs=").append(docs);
        sb.append(", audios=").append(audios);
        sb.append(", clipsFollowers=").append(clipsFollowers);
        sb.append(", articles=").append(articles);
        sb.append('}');
        return sb.toString();
    }
}


// Autogenerated from vk-api-schema. Please don't edit it manually.
package com.vk.api.sdk.objects.groups;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.vk.api.sdk.objects.Validable;
import java.util.Objects;

/**
 * CountersGroup object
 */
public class CountersGroup implements Validable {

    /**
     * Addresses number
     */
    @SerializedName("addresses")
    private Integer addresses;

    /**
     * Photo albums number
     */
    @SerializedName("albums")
    private Integer albums;

    /**
     * Audios number
     */
    @SerializedName("audios")
    private Integer audios;

    /**
     * Audio playlists number
     */
    @SerializedName("audio_playlists")
    private Integer audioPlaylists;

    /**
     * Docs number
     */
    @SerializedName("docs")
    private Integer docs;

    /**
     * Market items number
     */
    @SerializedName("market")
    private Integer market;

    /**
     * Photos number
     */
    @SerializedName("photos")
    private Integer photos;

    /**
     * Topics number
     */
    @SerializedName("topics")
    private Integer topics;

    /**
     * Videos number
     */
    @SerializedName("videos")
    private Integer videos;

    /**
     * Market services number
     */
    @SerializedName("market_services")
    private Integer marketServices;

    /**
     * Podcasts number
     */
    @SerializedName("podcasts")
    private Integer podcasts;

    /**
     * Articles number
     */
    @SerializedName("articles")
    private Integer articles;

    /**
     * Narratives number
     */
    @SerializedName("narratives")
    private Integer narratives;

    /**
     * Clips number
     */
    @SerializedName("clips")
    private Integer clips;

    /**
     * Clips followers number
     */
    @SerializedName("clips_followers")
    private Integer clipsFollowers;

    public Integer getAddresses() {
        return addresses;
    }

    public CountersGroup setAddresses(Integer addresses) {
        this.addresses = addresses;
        return this;
    }

    public Integer getAlbums() {
        return albums;
    }

    public CountersGroup setAlbums(Integer albums) {
        this.albums = albums;
        return this;
    }

    public Integer getAudios() {
        return audios;
    }

    public CountersGroup setAudios(Integer audios) {
        this.audios = audios;
        return this;
    }

    public Integer getAudioPlaylists() {
        return audioPlaylists;
    }

    public CountersGroup setAudioPlaylists(Integer audioPlaylists) {
        this.audioPlaylists = audioPlaylists;
        return this;
    }

    public Integer getDocs() {
        return docs;
    }

    public CountersGroup setDocs(Integer docs) {
        this.docs = docs;
        return this;
    }

    public Integer getMarket() {
        return market;
    }

    public CountersGroup setMarket(Integer market) {
        this.market = market;
        return this;
    }

    public Integer getPhotos() {
        return photos;
    }

    public CountersGroup setPhotos(Integer photos) {
        this.photos = photos;
        return this;
    }

    public Integer getTopics() {
        return topics;
    }

    public CountersGroup setTopics(Integer topics) {
        this.topics = topics;
        return this;
    }

    public Integer getVideos() {
        return videos;
    }

    public CountersGroup setVideos(Integer videos) {
        this.videos = videos;
        return this;
    }

    public Integer getMarketServices() {
        return marketServices;
    }

    public CountersGroup setMarketServices(Integer marketServices) {
        this.marketServices = marketServices;
        return this;
    }

    public Integer getPodcasts() {
        return podcasts;
    }

    public CountersGroup setPodcasts(Integer podcasts) {
        this.podcasts = podcasts;
        return this;
    }

    public Integer getArticles() {
        return articles;
    }

    public CountersGroup setArticles(Integer articles) {
        this.articles = articles;
        return this;
    }

    public Integer getNarratives() {
        return narratives;
    }

    public CountersGroup setNarratives(Integer narratives) {
        this.narratives = narratives;
        return this;
    }

    public Integer getClips() {
        return clips;
    }

    public CountersGroup setClips(Integer clips) {
        this.clips = clips;
        return this;
    }

    public Integer getClipsFollowers() {
        return clipsFollowers;
    }

    public CountersGroup setClipsFollowers(Integer clipsFollowers) {
        this.clipsFollowers = clipsFollowers;
        return this;
    }

    @Override
    public int hashCode() {
        return Objects.hash(addresses, albums, narratives, topics, clips, marketServices, videos, photos, market, podcasts, docs, audios, audioPlaylists, articles, clipsFollowers);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        CountersGroup countersGroup = (CountersGroup) o;
        return Objects.equals(addresses, countersGroup.addresses) && Objects.equals(albums, countersGroup.albums) && Objects.equals(narratives, countersGroup.narratives) && Objects.equals(topics, countersGroup.topics) && Objects.equals(clips, countersGroup.clips) && Objects.equals(audioPlaylists, countersGroup.audioPlaylists) && Objects.equals(videos, countersGroup.videos) && Objects.equals(marketServices, countersGroup.marketServices) && Objects.equals(photos, countersGroup.photos) && Objects.equals(market, countersGroup.market) && Objects.equals(podcasts, countersGroup.podcasts) && Objects.equals(docs, counter

sGroup.docs) && Objects.equals(audios, countersGroup.audios) && Objects.equals(clipsFollowers, countersGroup.clipsFollowers) && Objects.equals(articles, countersGroup.articles);
    }

    @Override
    public String toString() {
        final Gson gson = new Gson();
        return gson.toJson(this);
    }

    public String toPrettyString() {
        final StringBuilder sb = new StringBuilder("CountersGroup{");
        sb.append("addresses=").append(addresses);
        sb.append(", albums=").append(albums);
        sb.append(", narratives=").append(narratives);
        sb.append(", topics=").append(topics);
        sb.append(", clips=").append(clips);
        sb.append(", audioPlaylists=").append(audioPlaylists);
        sb.append(", videos=").append(videos);
        sb.append(", marketServices=").append(marketServices);
        sb.append(", photos=").append(photos);
        sb.append(", market=").append(market);
        sb.append(", podcasts=").append(podcasts);
        sb.append(", docs=").append(docs);
        sb.append(", audios=").append(audios);
        sb.append(", clipsFollowers=").append(clipsFollowers);
        sb.append(", articles=").append(articles);
        sb.append('}');
        return sb.toString();
    }
}