// This file was auto-generated by the veyron vdl tool.
// Source: repository.vdl

// Package repository contains implementation of the interface for
// storing and serving various veyron management objects.
package repository

import (
	"veyron/services/mgmt/profile"

	"veyron2/security"

	"veyron2/services/mgmt/application"

	"veyron2/services/mgmt/repository"

	// The non-user imports are prefixed with "_gen_" to prevent collisions.
	_gen_veyron2 "veyron2"
	_gen_context "veyron2/context"
	_gen_ipc "veyron2/ipc"
	_gen_naming "veyron2/naming"
	_gen_rt "veyron2/rt"
	_gen_vdlutil "veyron2/vdl/vdlutil"
	_gen_wiretype "veyron2/wiretype"
)

// Application describes an application repository internally. Besides
// the public Application interface, it allows to add and remove
// application envelopes.
// Application is the interface the client binds and uses.
// Application_ExcludingUniversal is the interface without internal framework-added methods
// to enable embedding without method collisions.  Not to be used directly by clients.
type Application_ExcludingUniversal interface {
	// Application provides access to application envelopes. An
	// application envelope is identified by an application name and an
	// application version, which are specified through the object name,
	// and a profile name, which is specified using a method argument.
	//
	// Example:
	// /apps/search/v1.Match([]string{"base", "media"})
	//   returns an application envelope that can be used for downloading
	//   and executing the "search" application, version "v1", runnable
	//   on either the "base" or "media" profile.
	repository.Application_ExcludingUniversal
	// Put adds the given tuple of application version (specified
	// through the object name suffix) and application envelope to all
	// of the given application profiles.
	Put(ctx _gen_context.T, Profiles []string, Envelope application.Envelope, opts ..._gen_ipc.CallOpt) (err error)
	// Remove removes the application envelope for the given profile
	// name and application version (specified through the object name
	// suffix). If no version is specified as part of the suffix, the
	// method removes all versions for the given profile.
	//
	// TODO(jsimsa): Add support for using "*" to specify all profiles
	// when Matt implements Globing (or Ken implements querying).
	Remove(ctx _gen_context.T, Profile string, opts ..._gen_ipc.CallOpt) (err error)
}
type Application interface {
	_gen_ipc.UniversalServiceMethods
	Application_ExcludingUniversal
}

// ApplicationService is the interface the server implements.
type ApplicationService interface {

	// Application provides access to application envelopes. An
	// application envelope is identified by an application name and an
	// application version, which are specified through the object name,
	// and a profile name, which is specified using a method argument.
	//
	// Example:
	// /apps/search/v1.Match([]string{"base", "media"})
	//   returns an application envelope that can be used for downloading
	//   and executing the "search" application, version "v1", runnable
	//   on either the "base" or "media" profile.
	repository.ApplicationService
	// Put adds the given tuple of application version (specified
	// through the object name suffix) and application envelope to all
	// of the given application profiles.
	Put(context _gen_ipc.ServerContext, Profiles []string, Envelope application.Envelope) (err error)
	// Remove removes the application envelope for the given profile
	// name and application version (specified through the object name
	// suffix). If no version is specified as part of the suffix, the
	// method removes all versions for the given profile.
	//
	// TODO(jsimsa): Add support for using "*" to specify all profiles
	// when Matt implements Globing (or Ken implements querying).
	Remove(context _gen_ipc.ServerContext, Profile string) (err error)
}

// BindApplication returns the client stub implementing the Application
// interface.
//
// If no _gen_ipc.Client is specified, the default _gen_ipc.Client in the
// global Runtime is used.
func BindApplication(name string, opts ..._gen_ipc.BindOpt) (Application, error) {
	var client _gen_ipc.Client
	switch len(opts) {
	case 0:
		client = _gen_rt.R().Client()
	case 1:
		switch o := opts[0].(type) {
		case _gen_veyron2.Runtime:
			client = o.Client()
		case _gen_ipc.Client:
			client = o
		default:
			return nil, _gen_vdlutil.ErrUnrecognizedOption
		}
	default:
		return nil, _gen_vdlutil.ErrTooManyOptionsToBind
	}
	stub := &clientStubApplication{client: client, name: name}
	stub.Application_ExcludingUniversal, _ = repository.BindApplication(name, client)

	return stub, nil
}

// NewServerApplication creates a new server stub.
//
// It takes a regular server implementing the ApplicationService
// interface, and returns a new server stub.
func NewServerApplication(server ApplicationService) interface{} {
	return &ServerStubApplication{
		ServerStubApplication: *repository.NewServerApplication(server).(*repository.ServerStubApplication),
		service:               server,
	}
}

// clientStubApplication implements Application.
type clientStubApplication struct {
	repository.Application_ExcludingUniversal

	client _gen_ipc.Client
	name   string
}

func (__gen_c *clientStubApplication) Put(ctx _gen_context.T, Profiles []string, Envelope application.Envelope, opts ..._gen_ipc.CallOpt) (err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Put", []interface{}{Profiles, Envelope}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubApplication) Remove(ctx _gen_context.T, Profile string, opts ..._gen_ipc.CallOpt) (err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Remove", []interface{}{Profile}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubApplication) UnresolveStep(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply []string, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "UnresolveStep", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubApplication) Signature(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply _gen_ipc.ServiceSignature, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Signature", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubApplication) GetMethodTags(ctx _gen_context.T, method string, opts ..._gen_ipc.CallOpt) (reply []interface{}, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "GetMethodTags", []interface{}{method}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

// ServerStubApplication wraps a server that implements
// ApplicationService and provides an object that satisfies
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubApplication struct {
	repository.ServerStubApplication

	service ApplicationService
}

func (__gen_s *ServerStubApplication) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
	// TODO(bprosnitz) GetMethodTags() will be replaces with Signature().
	// Note: This exhibits some weird behavior like returning a nil error if the method isn't found.
	// This will change when it is replaced with Signature().
	if resp, err := __gen_s.ServerStubApplication.GetMethodTags(call, method); resp != nil || err != nil {
		return resp, err
	}
	switch method {
	case "Put":
		return []interface{}{security.Label(2)}, nil
	case "Remove":
		return []interface{}{security.Label(2)}, nil
	default:
		return nil, nil
	}
}

func (__gen_s *ServerStubApplication) Signature(call _gen_ipc.ServerCall) (_gen_ipc.ServiceSignature, error) {
	result := _gen_ipc.ServiceSignature{Methods: make(map[string]_gen_ipc.MethodSignature)}
	result.Methods["Put"] = _gen_ipc.MethodSignature{
		InArgs: []_gen_ipc.MethodArgument{
			{Name: "Profiles", Type: 61},
			{Name: "Envelope", Type: 65},
		},
		OutArgs: []_gen_ipc.MethodArgument{
			{Name: "", Type: 66},
		},
	}
	result.Methods["Remove"] = _gen_ipc.MethodSignature{
		InArgs: []_gen_ipc.MethodArgument{
			{Name: "Profile", Type: 3},
		},
		OutArgs: []_gen_ipc.MethodArgument{
			{Name: "", Type: 66},
		},
	}

	result.TypeDefs = []_gen_vdlutil.Any{
		_gen_wiretype.StructType{
			[]_gen_wiretype.FieldType{
				_gen_wiretype.FieldType{Type: 0x3, Name: "Title"},
				_gen_wiretype.FieldType{Type: 0x3d, Name: "Args"},
				_gen_wiretype.FieldType{Type: 0x3, Name: "Binary"},
				_gen_wiretype.FieldType{Type: 0x3d, Name: "Env"},
			},
			"veyron2/services/mgmt/application.Envelope", []string(nil)},
		_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
	var ss _gen_ipc.ServiceSignature
	var firstAdded int
	ss, _ = __gen_s.ServerStubApplication.Signature(call)
	firstAdded = len(result.TypeDefs)
	for k, v := range ss.Methods {
		for i, _ := range v.InArgs {
			if v.InArgs[i].Type >= _gen_wiretype.TypeIDFirst {
				v.InArgs[i].Type += _gen_wiretype.TypeID(firstAdded)
			}
		}
		for i, _ := range v.OutArgs {
			if v.OutArgs[i].Type >= _gen_wiretype.TypeIDFirst {
				v.OutArgs[i].Type += _gen_wiretype.TypeID(firstAdded)
			}
		}
		if v.InStream >= _gen_wiretype.TypeIDFirst {
			v.InStream += _gen_wiretype.TypeID(firstAdded)
		}
		if v.OutStream >= _gen_wiretype.TypeIDFirst {
			v.OutStream += _gen_wiretype.TypeID(firstAdded)
		}
		result.Methods[k] = v
	}
	//TODO(bprosnitz) combine type definitions from embeded interfaces in a way that doesn't cause duplication.
	for _, d := range ss.TypeDefs {
		switch wt := d.(type) {
		case _gen_wiretype.SliceType:
			if wt.Elem >= _gen_wiretype.TypeIDFirst {
				wt.Elem += _gen_wiretype.TypeID(firstAdded)
			}
			d = wt
		case _gen_wiretype.ArrayType:
			if wt.Elem >= _gen_wiretype.TypeIDFirst {
				wt.Elem += _gen_wiretype.TypeID(firstAdded)
			}
			d = wt
		case _gen_wiretype.MapType:
			if wt.Key >= _gen_wiretype.TypeIDFirst {
				wt.Key += _gen_wiretype.TypeID(firstAdded)
			}
			if wt.Elem >= _gen_wiretype.TypeIDFirst {
				wt.Elem += _gen_wiretype.TypeID(firstAdded)
			}
			d = wt
		case _gen_wiretype.StructType:
			for i, fld := range wt.Fields {
				if fld.Type >= _gen_wiretype.TypeIDFirst {
					wt.Fields[i].Type += _gen_wiretype.TypeID(firstAdded)
				}
			}
			d = wt
			// NOTE: other types are missing, but we are upgrading anyways.
		}
		result.TypeDefs = append(result.TypeDefs, d)
	}

	return result, nil
}

func (__gen_s *ServerStubApplication) UnresolveStep(call _gen_ipc.ServerCall) (reply []string, err error) {
	if unresolver, ok := __gen_s.service.(_gen_ipc.Unresolver); ok {
		return unresolver.UnresolveStep(call)
	}
	if call.Server() == nil {
		return
	}
	var published []string
	if published, err = call.Server().Published(); err != nil || published == nil {
		return
	}
	reply = make([]string, len(published))
	for i, p := range published {
		reply[i] = _gen_naming.Join(p, call.Name())
	}
	return
}

func (__gen_s *ServerStubApplication) Put(call _gen_ipc.ServerCall, Profiles []string, Envelope application.Envelope) (err error) {
	err = __gen_s.service.Put(call, Profiles, Envelope)
	return
}

func (__gen_s *ServerStubApplication) Remove(call _gen_ipc.ServerCall, Profile string) (err error) {
	err = __gen_s.service.Remove(call, Profile)
	return
}

// Profile describes a profile internally. Besides the public Profile
// interface, it allows to add and remove profile specifications.
// Profile is the interface the client binds and uses.
// Profile_ExcludingUniversal is the interface without internal framework-added methods
// to enable embedding without method collisions.  Not to be used directly by clients.
type Profile_ExcludingUniversal interface {
	// Profile abstracts a device's ability to run binaries, and hides
	// specifics such as the operating system, hardware architecture, and
	// the set of installed libraries. Profiles describe binaries and
	// devices, and are used to match them.
	repository.Profile_ExcludingUniversal
	// Specification returns the profile specification for the profile
	// identified through the object name suffix.
	Specification(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply profile.Specification, err error)
	// Put sets the profile specification for the profile identified
	// through the object name suffix.
	Put(ctx _gen_context.T, Specification profile.Specification, opts ..._gen_ipc.CallOpt) (err error)
	// Remove removes the profile specification for the profile
	// identified through the object name suffix.
	Remove(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error)
}
type Profile interface {
	_gen_ipc.UniversalServiceMethods
	Profile_ExcludingUniversal
}

// ProfileService is the interface the server implements.
type ProfileService interface {

	// Profile abstracts a device's ability to run binaries, and hides
	// specifics such as the operating system, hardware architecture, and
	// the set of installed libraries. Profiles describe binaries and
	// devices, and are used to match them.
	repository.ProfileService
	// Specification returns the profile specification for the profile
	// identified through the object name suffix.
	Specification(context _gen_ipc.ServerContext) (reply profile.Specification, err error)
	// Put sets the profile specification for the profile identified
	// through the object name suffix.
	Put(context _gen_ipc.ServerContext, Specification profile.Specification) (err error)
	// Remove removes the profile specification for the profile
	// identified through the object name suffix.
	Remove(context _gen_ipc.ServerContext) (err error)
}

// BindProfile returns the client stub implementing the Profile
// interface.
//
// If no _gen_ipc.Client is specified, the default _gen_ipc.Client in the
// global Runtime is used.
func BindProfile(name string, opts ..._gen_ipc.BindOpt) (Profile, error) {
	var client _gen_ipc.Client
	switch len(opts) {
	case 0:
		client = _gen_rt.R().Client()
	case 1:
		switch o := opts[0].(type) {
		case _gen_veyron2.Runtime:
			client = o.Client()
		case _gen_ipc.Client:
			client = o
		default:
			return nil, _gen_vdlutil.ErrUnrecognizedOption
		}
	default:
		return nil, _gen_vdlutil.ErrTooManyOptionsToBind
	}
	stub := &clientStubProfile{client: client, name: name}
	stub.Profile_ExcludingUniversal, _ = repository.BindProfile(name, client)

	return stub, nil
}

// NewServerProfile creates a new server stub.
//
// It takes a regular server implementing the ProfileService
// interface, and returns a new server stub.
func NewServerProfile(server ProfileService) interface{} {
	return &ServerStubProfile{
		ServerStubProfile: *repository.NewServerProfile(server).(*repository.ServerStubProfile),
		service:           server,
	}
}

// clientStubProfile implements Profile.
type clientStubProfile struct {
	repository.Profile_ExcludingUniversal

	client _gen_ipc.Client
	name   string
}

func (__gen_c *clientStubProfile) Specification(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply profile.Specification, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Specification", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubProfile) Put(ctx _gen_context.T, Specification profile.Specification, opts ..._gen_ipc.CallOpt) (err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Put", []interface{}{Specification}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubProfile) Remove(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Remove", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubProfile) UnresolveStep(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply []string, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "UnresolveStep", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubProfile) Signature(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply _gen_ipc.ServiceSignature, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Signature", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

func (__gen_c *clientStubProfile) GetMethodTags(ctx _gen_context.T, method string, opts ..._gen_ipc.CallOpt) (reply []interface{}, err error) {
	var call _gen_ipc.Call
	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "GetMethodTags", []interface{}{method}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&reply, &err); ierr != nil {
		err = ierr
	}
	return
}

// ServerStubProfile wraps a server that implements
// ProfileService and provides an object that satisfies
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubProfile struct {
	repository.ServerStubProfile

	service ProfileService
}

func (__gen_s *ServerStubProfile) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
	// TODO(bprosnitz) GetMethodTags() will be replaces with Signature().
	// Note: This exhibits some weird behavior like returning a nil error if the method isn't found.
	// This will change when it is replaced with Signature().
	if resp, err := __gen_s.ServerStubProfile.GetMethodTags(call, method); resp != nil || err != nil {
		return resp, err
	}
	switch method {
	case "Specification":
		return []interface{}{security.Label(1)}, nil
	case "Put":
		return []interface{}{security.Label(2)}, nil
	case "Remove":
		return []interface{}{security.Label(2)}, nil
	default:
		return nil, nil
	}
}

func (__gen_s *ServerStubProfile) Signature(call _gen_ipc.ServerCall) (_gen_ipc.ServiceSignature, error) {
	result := _gen_ipc.ServiceSignature{Methods: make(map[string]_gen_ipc.MethodSignature)}
	result.Methods["Put"] = _gen_ipc.MethodSignature{
		InArgs: []_gen_ipc.MethodArgument{
			{Name: "Specification", Type: 70},
		},
		OutArgs: []_gen_ipc.MethodArgument{
			{Name: "", Type: 71},
		},
	}
	result.Methods["Remove"] = _gen_ipc.MethodSignature{
		InArgs: []_gen_ipc.MethodArgument{},
		OutArgs: []_gen_ipc.MethodArgument{
			{Name: "", Type: 71},
		},
	}
	result.Methods["Specification"] = _gen_ipc.MethodSignature{
		InArgs: []_gen_ipc.MethodArgument{},
		OutArgs: []_gen_ipc.MethodArgument{
			{Name: "", Type: 70},
			{Name: "", Type: 71},
		},
	}

	result.TypeDefs = []_gen_vdlutil.Any{
		_gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "veyron2/services/mgmt/build.Architecture", Tags: []string(nil)}, _gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "veyron2/services/mgmt/build.Format", Tags: []string(nil)}, _gen_wiretype.StructType{
			[]_gen_wiretype.FieldType{
				_gen_wiretype.FieldType{Type: 0x3, Name: "Name"},
				_gen_wiretype.FieldType{Type: 0x3, Name: "MajorVersion"},
				_gen_wiretype.FieldType{Type: 0x3, Name: "MinorVersion"},
			},
			"veyron/services/mgmt/profile.Library", []string(nil)},
		_gen_wiretype.MapType{Key: 0x43, Elem: 0x2, Name: "", Tags: []string(nil)}, _gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "veyron2/services/mgmt/build.OperatingSystem", Tags: []string(nil)}, _gen_wiretype.StructType{
			[]_gen_wiretype.FieldType{
				_gen_wiretype.FieldType{Type: 0x41, Name: "Arch"},
				_gen_wiretype.FieldType{Type: 0x3, Name: "Description"},
				_gen_wiretype.FieldType{Type: 0x42, Name: "Format"},
				_gen_wiretype.FieldType{Type: 0x44, Name: "Libraries"},
				_gen_wiretype.FieldType{Type: 0x3, Name: "Label"},
				_gen_wiretype.FieldType{Type: 0x45, Name: "OS"},
			},
			"veyron/services/mgmt/profile.Specification", []string(nil)},
		_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
	var ss _gen_ipc.ServiceSignature
	var firstAdded int
	ss, _ = __gen_s.ServerStubProfile.Signature(call)
	firstAdded = len(result.TypeDefs)
	for k, v := range ss.Methods {
		for i, _ := range v.InArgs {
			if v.InArgs[i].Type >= _gen_wiretype.TypeIDFirst {
				v.InArgs[i].Type += _gen_wiretype.TypeID(firstAdded)
			}
		}
		for i, _ := range v.OutArgs {
			if v.OutArgs[i].Type >= _gen_wiretype.TypeIDFirst {
				v.OutArgs[i].Type += _gen_wiretype.TypeID(firstAdded)
			}
		}
		if v.InStream >= _gen_wiretype.TypeIDFirst {
			v.InStream += _gen_wiretype.TypeID(firstAdded)
		}
		if v.OutStream >= _gen_wiretype.TypeIDFirst {
			v.OutStream += _gen_wiretype.TypeID(firstAdded)
		}
		result.Methods[k] = v
	}
	//TODO(bprosnitz) combine type definitions from embeded interfaces in a way that doesn't cause duplication.
	for _, d := range ss.TypeDefs {
		switch wt := d.(type) {
		case _gen_wiretype.SliceType:
			if wt.Elem >= _gen_wiretype.TypeIDFirst {
				wt.Elem += _gen_wiretype.TypeID(firstAdded)
			}
			d = wt
		case _gen_wiretype.ArrayType:
			if wt.Elem >= _gen_wiretype.TypeIDFirst {
				wt.Elem += _gen_wiretype.TypeID(firstAdded)
			}
			d = wt
		case _gen_wiretype.MapType:
			if wt.Key >= _gen_wiretype.TypeIDFirst {
				wt.Key += _gen_wiretype.TypeID(firstAdded)
			}
			if wt.Elem >= _gen_wiretype.TypeIDFirst {
				wt.Elem += _gen_wiretype.TypeID(firstAdded)
			}
			d = wt
		case _gen_wiretype.StructType:
			for i, fld := range wt.Fields {
				if fld.Type >= _gen_wiretype.TypeIDFirst {
					wt.Fields[i].Type += _gen_wiretype.TypeID(firstAdded)
				}
			}
			d = wt
			// NOTE: other types are missing, but we are upgrading anyways.
		}
		result.TypeDefs = append(result.TypeDefs, d)
	}

	return result, nil
}

func (__gen_s *ServerStubProfile) UnresolveStep(call _gen_ipc.ServerCall) (reply []string, err error) {
	if unresolver, ok := __gen_s.service.(_gen_ipc.Unresolver); ok {
		return unresolver.UnresolveStep(call)
	}
	if call.Server() == nil {
		return
	}
	var published []string
	if published, err = call.Server().Published(); err != nil || published == nil {
		return
	}
	reply = make([]string, len(published))
	for i, p := range published {
		reply[i] = _gen_naming.Join(p, call.Name())
	}
	return
}

func (__gen_s *ServerStubProfile) Specification(call _gen_ipc.ServerCall) (reply profile.Specification, err error) {
	reply, err = __gen_s.service.Specification(call)
	return
}

func (__gen_s *ServerStubProfile) Put(call _gen_ipc.ServerCall, Specification profile.Specification) (err error) {
	err = __gen_s.service.Put(call, Specification)
	return
}

func (__gen_s *ServerStubProfile) Remove(call _gen_ipc.ServerCall) (err error) {
	err = __gen_s.service.Remove(call)
	return
}
