// Path: cocaine-client/src/main/java/cocaine/ServiceApi.java
// public class ServiceApi {
// 
//     private final String name;
//     private final ImmutableMap<String, Integer> api;
// 
//     public ServiceApi(String name, ImmutableMap<String, Integer> api) {
//         this.name = name;
//         this.api = api;
//     }
// 
//     public static ServiceApi of(String name, String method, int id) {
//         return new ServiceApi(name, ImmutableMap.of(method, id));
//     }
// 
//     public static ServiceApi of(String name, ImmutableMap<String, Integer> methods) {
//         return new ServiceApi(name, methods);
//     }
// 
//     public int getMethod(String method) {
//         Integer number = api.get(method);
//         if (number == null) {
//             throw new UnknownServiceMethodException(name, method);
//         }
//         return number;
//     }
// 
//     @Override
//     public String toString() {
//         return "Service: " + name + "; Service API: { "
//                 + Joiner.on(", ").withKeyValueSeparator(": ").join(api) + " }";
//     }
// }
// 
// Path: cocaine-client/src/main/java/cocaine/ServiceInfo.java
// public class ServiceInfo {
// 
//     private final String name;
//     private final SocketAddress endpoint;
//     private final ServiceApi api;
// 
//     public ServiceInfo(String name, SocketAddress endpoint, ServiceApi api) {
//         this.name = name;
//         this.endpoint = endpoint;
//         this.api = api;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public SocketAddress getEndpoint() {
//         return endpoint;
//     }
// 
//     public ServiceApi getApi() {
//         return api;
//     }
// 
//     @Override
//     public String toString() {
//         return "Service: " + name + "; Endpoint: " + endpoint + "; Service API: { " + api.toString() + " }";
//     }
// }


import java.io.IOException;
import java.net.SocketAddress;
import java.util.Map;
import cocaine.ServiceApi;
import cocaine.ServiceInfo;
import com.google.common.collect.ImmutableBiMap;
import org.msgpack.packer.Packer;
import org.msgpack.template.AbstractTemplate;
import org.msgpack.template.Template;
import org.msgpack.template.Templates;
import org.msgpack.unpacker.Unpacker;
package cocaine.msgpack;



/**
 * @author Anton Bobukh <abobukh@yandex-team.ru>
 */
public class ServiceInfoTemplate extends AbstractTemplate<ServiceInfo> {

    private final String name;

    private ServiceInfoTemplate(String name) {
        this.name = name;
    }

    public static Template<ServiceInfo> create(String name) {
        return new ServiceInfoTemplate(name);
    }

    @Override
    public void write(Packer packer, ServiceInfo service, boolean required) throws IOException {
        throw new UnsupportedOperationException(ServiceInfo.class.getSimpleName()
                + " can not be encoded by " + ServiceInfoTemplate.class.getSimpleName());
    }

    @Override
    public ServiceInfo read(Unpacker unpacker, ServiceInfo service, boolean required) throws IOException {
        unpacker.readArrayBegin();
        SocketAddress endpoint = unpacker.read(SocketAddressTemplate.getInstance());
        unpacker.readInt();
        Map<Integer, String> api = unpacker.read(Templates.tMap(Templates.TInteger, Templates.TString));
        unpacker.readArrayEnd();

// Path: cocaine-client/src/main/java/cocaine/ServiceApi.java
// public class ServiceApi {
// 
//     private final String name;
//     private final ImmutableMap<String, Integer> api;
// 
//     public ServiceApi(String name, ImmutableMap<String, Integer> api) {
//         this.name = name;
//         this.api = api;
//     }
// 
//     public static ServiceApi of(String name, String method, int id) {
//         return new ServiceApi(name, ImmutableMap.of(method, id));
//     }
// 
//     public static ServiceApi of(String name, ImmutableMap<String, Integer> methods) {
//         return new ServiceApi(name, methods);
//     }
// 
//     public int getMethod(String method) {
//         Integer number = api.get(method);
//         if (number == null) {
//             throw new UnknownServiceMethodException(name, method);
//         }
//         return number;
//     }
// 
//     @Override
//     public String toString() {
//         return "Service: " + name + "; Service API: { "
//                 + Joiner.on(", ").withKeyValueSeparator(": ").join(api) + " }";
//     }
// }
// 
// Path: cocaine-client/src/main/java/cocaine/ServiceInfo.java
// public class ServiceInfo {
// 
//     private final String name;
//     private final SocketAddress endpoint;
//     private final ServiceApi api;
// 
//     public ServiceInfo(String name, SocketAddress endpoint, ServiceApi api) {
//         this.name = name;
//         this.endpoint = endpoint;
//         this.api = api;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public SocketAddress getEndpoint() {
//         return endpoint;
//     }
// 
//     public ServiceApi getApi() {
//         return api;
//     }
// 
//     @Override
//     public String toString() {
//         return "Service: " + name + "; Endpoint: " + endpoint + "; Service API: { " + api.toString() + " }";
//     }
// }


// Path: cocaine-client/src/main/java/cocaine/msgpack/ServiceInfoTemplate.java
import java.io.IOException;
import java.net.SocketAddress;
import java.util.Map;
import cocaine.ServiceApi;
import cocaine.ServiceInfo;
import com.google.common.collect.ImmutableBiMap;
import org.msgpack.packer.Packer;
import org.msgpack.template.AbstractTemplate;
import org.msgpack.template.Template;
import org.msgpack.template.Templates;
import org.msgpack.unpacker.Unpacker;

package cocaine.msgpack;



/**
 * @author Anton Bobukh <abobukh@yandex-team.ru>
 */
public class ServiceInfoTemplate extends AbstractTemplate<ServiceInfo> {

    private final String name;

    private ServiceInfoTemplate(String name) {
        this.name = name;
    }

    public static Template<ServiceInfo> create(String name) {
        return new ServiceInfoTemplate(name);
    }

    @Override
    public void write(Packer packer, ServiceInfo service, boolean required) throws IOException {
        throw new UnsupportedOperationException(ServiceInfo.class.getSimpleName()
                + " can not be encoded by " + ServiceInfoTemplate.class.getSimpleName());
    }

    @Override
    public ServiceInfo read(Unpacker unpacker, ServiceInfo service, boolean required) throws IOException {
        unpacker.readArrayBegin();
        SocketAddress endpoint = unpacker.read(SocketAddressTemplate.getInstance());
        unpacker.readInt();
        Map<Integer, String> api = unpacker.read(Templates.tMap(Templates.TInteger, Templates.TString));
        unpacker.readArrayEnd();

        return new ServiceInfo(name, endpoint, ServiceApi.of(name, ImmutableBiMap.copyOf(api).inverse()));