<commit_before>package yext

// ListECLResponse is a calculated value that provides typed access to an underlying 'ListECL' response
type ListECLResponse struct {
	AllLists     []*ECL
	ProductLists []*ProductsECL
	BioLists     []*BiosECL
	EventsLists  []*EventsECL
}

type ECL struct {
	Id       *string       `json:"id"`
	Name     *string       `json:"name,omitempty"`  // max length 100
	Title    *string       `json:"title,omitempty"` // max length 100
	Type     *string       `json:"type,omitempty"`  // one of MENU, BIOS, PRODUCTS, EVENTS
	Size     *int          `json:"size,omitempty"`  // read only
	Publish  *bool         `json:"publish"`
	Currency *string       `json:"currency,omitempty"` // ISO Code for currency
	Sections []*ECLSection `json:"sections,omitempty"`
}

func (e ECL) GetId() string {
	if e.Id != nil {
		return *e.Id
	}
	return ""
}

func (e ECL) GetName() string {
	if e.Name != nil {
		return *e.Name
	}
	return ""
}

func (e ECL) GetTitle() string {
	if e.Title != nil {
		return *e.Title
	}
	return ""
}

func (e ECL) GetType() string {
	if e.Type != nil {
		return *e.Type
	}
	return ""
}

func (e ECL) GetSize() int {
	if e.Size != nil {
		return *e.Size
	}
	return -1
}

func (e ECL) GetPublish() bool {
	if e.Publish != nil {
		return *e.Publish
	}
	return false
}

func (e ECL) GetCurrency() string {
	if e.Currency != nil {
		return *e.Currency
	}
	return ""
}

type ECLSection struct {
	Id          *string `json:"id"`
	Name        *string `json:"name,omitempty"`
	Description *string `json:"description,omitempty"`
}

func (e ECLSection) GetId() string {
	if e.Id != nil {
		return *e.Id
	}
	return ""
}

func (e ECLSection) GetName() string {
	if e.Name != nil {
		return *e.Name
	}
	return ""
}

func (e ECLSection) GetDescription() string {
	if e.Description != nil {
		return *e.Description
	}
	return ""
}

type ECLItem struct {
	Id          *string `json:"id"`
	Name        *string `json:"name,omitempty"`
	Description *string `json:"description,omitempty"`
}

func (e ECLItem) GetId() string {
	if e.Id != nil {
		return *e.Id
	}
	return ""
}

func (e ECLItem) GetName() string {
	if e.Name != nil {
		return *e.Name
	}
	return ""
}

func (e ECLItem) GetDescription() string {
	if e.Description != nil {
		return *e.Description
	}
	return ""
}

type EclPhoto struct {
	Url    string `json:"url"`
	Height int    `json:"height,omitempty"`
	Width  int    `json:"width,omitempty"`
}

type Cost struct {
	Type    string         `json:"type,omitempty"`
	Price   string         `json:"price,omitempty"`
	Unit    string         `json:"unit,omitempty"`
	RangeTo string         `json:"rangeTo,omitempty"`
	Other   string         `json:"other,omitempty"`
	Options []*CostOptions `json:"options,omitempty"`
}

type CostOptions struct {
	Name    string `json:"name,omitempty"`
	Price   string `json:"price,omitempty"`
	Calorie int    `json:"calorie,omitempty"`
}

type EventsECL struct {
	ECL
	Sections []*EventsECLSection `json:"sections,omitempty"`
}

type EventsECLSection struct {
	ECLSection
	Items []*Event `json:"items,omitempty"` // max 100 items
}

type Event struct {
	ECLItem
	Type   string      `json:"type,omitempty"`
	Starts string      `json:"starts,omitempty"`
	Ends   string      `json:"ends,omitempty"`
	Photos []*EclPhoto `json:"photos,omitempty"`
	Url    string      `json:"url,omitempty"`
}

type ProductsECL struct {
	ECL
	Sections []*ProductsECLSection `json:"sections,omitempty"`
}

type ProductsECLSection struct {
	ECLSection
	Items []*Product `json:"items,omitempty"` // max 100 items
}

type Product struct {
	ECLItem
	Type   string      `json:"idcode,omitempty"`
	Cost   *Cost       `json:"cost,omitempty"`
	Photos []*EclPhoto `json:"photos,omitempty"`
	Video  string      `json:"video,omitempty"`
	Url    string      `json:"url,omitempty"`
}

type BiosECL struct {
	ECL
	Sections []*BiosECLSection `json:"sections,omitempty"`
}

type BiosECLSection struct {
	ECLSection
	Items []*Bio `json:"items,omitempty"` // max 100 items
}

type Bio struct {
	ECLItem
	Title          string    `json:"title,omitempty"`
	Photo          *EclPhoto `json:"photo,omitempty"`
	PhoneNumber    string    `json:"phone,omitempty"`
	EmailAddress   string    `json:"email,omitempty"`
	Education      []string  `json:"education"`
	Certifications []string  `json:"certifications"`
	Services       []string  `json:"services,omitempty"`
	Url            string    `json:"url,omitempty"`
}
<commit_msg>Add compare for Bios ECL Items r=mhupman<commit_after>package yext

import "reflect"

// ListECLResponse is a calculated value that provides typed access to an underlying 'ListECL' response
type ListECLResponse struct {
	AllLists     []*ECL
	ProductLists []*ProductsECL
	BioLists     []*BiosECL
	EventsLists  []*EventsECL
}

type ECL struct {
	Id       *string       `json:"id"`
	Name     *string       `json:"name,omitempty"`  // max length 100
	Title    *string       `json:"title,omitempty"` // max length 100
	Type     *string       `json:"type,omitempty"`  // one of MENU, BIOS, PRODUCTS, EVENTS
	Size     *int          `json:"size,omitempty"`  // read only
	Publish  *bool         `json:"publish"`
	Currency *string       `json:"currency,omitempty"` // ISO Code for currency
	Sections []*ECLSection `json:"sections,omitempty"`
}

func (e ECL) GetId() string {
	if e.Id != nil {
		return *e.Id
	}
	return ""
}

func (e ECL) GetName() string {
	if e.Name != nil {
		return *e.Name
	}
	return ""
}

func (e ECL) GetTitle() string {
	if e.Title != nil {
		return *e.Title
	}
	return ""
}

func (e ECL) GetType() string {
	if e.Type != nil {
		return *e.Type
	}
	return ""
}

func (e ECL) GetSize() int {
	if e.Size != nil {
		return *e.Size
	}
	return -1
}

func (e ECL) GetPublish() bool {
	if e.Publish != nil {
		return *e.Publish
	}
	return false
}

func (e ECL) GetCurrency() string {
	if e.Currency != nil {
		return *e.Currency
	}
	return ""
}

type ECLSection struct {
	Id          *string `json:"id"`
	Name        *string `json:"name,omitempty"`
	Description *string `json:"description,omitempty"`
}

func (e ECLSection) GetId() string {
	if e.Id != nil {
		return *e.Id
	}
	return ""
}

func (e ECLSection) GetName() string {
	if e.Name != nil {
		return *e.Name
	}
	return ""
}

func (e ECLSection) GetDescription() string {
	if e.Description != nil {
		return *e.Description
	}
	return ""
}

type ECLItem struct {
	Id          *string `json:"id"`
	Name        *string `json:"name,omitempty"`
	Description *string `json:"description,omitempty"`
}

func (e ECLItem) GetId() string {
	if e.Id != nil {
		return *e.Id
	}
	return ""
}

func (e ECLItem) GetName() string {
	if e.Name != nil {
		return *e.Name
	}
	return ""
}

func (e ECLItem) GetDescription() string {
	if e.Description != nil {
		return *e.Description
	}
	return ""
}

type EclPhoto struct {
	Url    string `json:"url"`
	Height int    `json:"height,omitempty"`
	Width  int    `json:"width,omitempty"`
}

type Cost struct {
	Type    string         `json:"type,omitempty"`
	Price   string         `json:"price,omitempty"`
	Unit    string         `json:"unit,omitempty"`
	RangeTo string         `json:"rangeTo,omitempty"`
	Other   string         `json:"other,omitempty"`
	Options []*CostOptions `json:"options,omitempty"`
}

type CostOptions struct {
	Name    string `json:"name,omitempty"`
	Price   string `json:"price,omitempty"`
	Calorie int    `json:"calorie,omitempty"`
}

type EventsECL struct {
	ECL
	Sections []*EventsECLSection `json:"sections,omitempty"`
}

type EventsECLSection struct {
	ECLSection
	Items []*Event `json:"items,omitempty"` // max 100 items
}

type Event struct {
	ECLItem
	Type   string      `json:"type,omitempty"`
	Starts string      `json:"starts,omitempty"`
	Ends   string      `json:"ends,omitempty"`
	Photos []*EclPhoto `json:"photos,omitempty"`
	Url    string      `json:"url,omitempty"`
}

type ProductsECL struct {
	ECL
	Sections []*ProductsECLSection `json:"sections,omitempty"`
}

type ProductsECLSection struct {
	ECLSection
	Items []*Product `json:"items,omitempty"` // max 100 items
}

type Product struct {
	ECLItem
	Type   string      `json:"idcode,omitempty"`
	Cost   *Cost       `json:"cost,omitempty"`
	Photos []*EclPhoto `json:"photos,omitempty"`
	Video  string      `json:"video,omitempty"`
	Url    string      `json:"url,omitempty"`
}

type BiosECL struct {
	ECL
	Sections []*BiosECLSection `json:"sections,omitempty"`
}

type BiosECLSection struct {
	ECLSection
	Items []*Bio `json:"items,omitempty"` // max 100 items
}

type Bio struct {
	ECLItem
	Title          string    `json:"title,omitempty"`
	Photo          *EclPhoto `json:"photo,omitempty"`
	PhoneNumber    string    `json:"phone,omitempty"`
	EmailAddress   string    `json:"email,omitempty"`
	Education      []string  `json:"education"`
	Certifications []string  `json:"certifications"`
	Services       []string  `json:"services,omitempty"`
	Url            string    `json:"url,omitempty"`
}

func BioItemCompare(itemA Bio, itemB Bio) bool {
	return reflect.DeepEqual(itemA, itemB)
}
<|endoftext|>


<commit_before>package eve

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
)
const eveUrl string = "https://api.eveonline.com"

var charactersCache = make(map[string]CharactersResult)

type Character struct {
	Name	string	`xml:"name,attr"`
	ID	string	`xml:"characterID,attr"`
	Corporation	string	`xml:"corporationName,attr"`
	CorporationID	string	`xml:"corporationID,attr"`
}

type CharactersResult struct {
	XMLName		xml.Name	`xml:"eveapi"`
	CurrentTime	string		`xml:"currentTime"`
	Characters	[]Character	`xml:"result>rowset>row"`
	CachedUntil	string		`xml:"cachedUntil"`
}

// Characters fetches, parses and returns a set of Eve Online characters.
func Characters(keyID string, vCode string) (res []Character) {
	var v CharactersResult

	cacheKey := fmt.Sprintf("%s:%s", keyID, vCode)
	if cachedResult, ok := charactersCache[cacheKey]; ok {
		if cacheEntryValid(cachedResult) {
			fmt.Println("Found cached character result")
			return cachedResult.Characters
		}
	}

	url := fmt.Sprintf("%s/account/Characters.xml.aspx?keyID=%s&vCode=%s", eveUrl, keyID, vCode)
	data, err := fetch(url)
	if err != nil {
		fmt.Printf("Fetch error: %v\n", err)
		return
	}

	err = xml.Unmarshal(data, &v)
	if err != nil {
		fmt.Printf("Unmarshal error: %v\n", err)
		return
	}

	fmt.Println("Storing result into cache:", cacheKey)
	charactersCache[cacheKey] = v
	return v.Characters
}

func fetch(url string) ([]byte, error) {
	res, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	data, err := ioutil.ReadAll(res.Body)
	res.Body.Close()

	if err != nil {
		return nil, err
	}
	return []byte(data), nil
}

func cacheEntryValid(entry CharactersResult) bool {
	t, err := time.Parse("2006-01-02 15:04:05", entry.CachedUntil)
	if err != nil {
		fmt.Println(err)
	}

	if t.After(time.Now()) {
		return true
	}
	return false
}
<commit_msg>Added account balance. This is due for a refactor.<commit_after>package eve

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
)
const eveUrl string = "https://api.eveonline.com"

var charactersCache = make(map[string]charactersResult)
var accountBalancesCache = make(map[string]accountBalanceResult)

type AccountBalance struct {
	ID	string	`xml:"accountID,attr"`
	Key	string	`xml:"accountKey,attr"`
	Balance	string	`xml:"balance,attr"`
}

type accountBalanceResult struct {
	XMLName		xml.Name		`xml:"eveapi"`
	CurrentTime	string			`xml:"currentTime"`
	AccountBalances	[]AccountBalance	`xml:"result>rowset>row"`
	CachedUntil	string			`xml:"cachedUntil"`
}

type Character struct {
	Name	string	`xml:"name,attr"`
	ID	string	`xml:"characterID,attr"`
	Corporation	string	`xml:"corporationName,attr"`
	CorporationID	string	`xml:"corporationID,attr"`
}

type charactersResult struct {
	XMLName		xml.Name	`xml:"eveapi"`
	CurrentTime	string		`xml:"currentTime"`
	Characters	[]Character	`xml:"result>rowset>row"`
	CachedUntil	string		`xml:"cachedUntil"`
}

// Characters fetches, parses and returns a set of Eve Online characters.
func AccountBalances(characterID string, keyID string, vCode string) (res []AccountBalance) {
	var v accountBalanceResult

	cacheKey := fmt.Sprintf("%s:%s:%s", characterID, keyID, vCode)
	if cachedResult, ok := accountBalancesCache[cacheKey]; ok {
		if cacheAccountBalanceEntryValid(cachedResult) {
			fmt.Println("Found cached account balance result")
			return cachedResult.AccountBalances
		}
	}

	url := fmt.Sprintf("%s/char/AccountBalance.xml.aspx?characterID=%s&keyID=%s&vCode=%s", eveUrl, characterID, keyID, vCode)
	data, err := fetch(url)
	if err != nil {
		fmt.Printf("Fetch error: %v\n", err)
		return
	}

	err = xml.Unmarshal(data, &v)
	if err != nil {
		fmt.Printf("Unmarshal error: %v\n", err)
		return
	}

	fmt.Println("Storing result into cache:", cacheKey)
	accountBalancesCache[cacheKey] = v
	return v.AccountBalances
}

// Characters fetches, parses and returns a set of Eve Online characters.
func Characters(keyID string, vCode string) (res []Character) {
	var v charactersResult

	cacheKey := fmt.Sprintf("%s:%s", keyID, vCode)
	if cachedResult, ok := charactersCache[cacheKey]; ok {
		if cacheEntryValid(cachedResult) {
			fmt.Println("Found cached character result")
			return cachedResult.Characters
		}
	}

	url := fmt.Sprintf("%s/account/Characters.xml.aspx?keyID=%s&vCode=%s", eveUrl, keyID, vCode)
	data, err := fetch(url)
	if err != nil {
		fmt.Printf("Fetch error: %v\n", err)
		return
	}

	err = xml.Unmarshal(data, &v)
	if err != nil {
		fmt.Printf("Unmarshal error: %v\n", err)
		return
	}

	fmt.Println("Storing result into cache:", cacheKey)
	charactersCache[cacheKey] = v
	return v.Characters
}

func fetch(url string) ([]byte, error) {
	res, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	data, err := ioutil.ReadAll(res.Body)
	res.Body.Close()

	if err != nil {
		return nil, err
	}
	return []byte(data), nil
}

func cacheAccountBalanceEntryValid(entry accountBalanceResult) bool {
	t, err := time.Parse("2006-01-02 15:04:05", entry.CachedUntil)
	if err != nil {
		fmt.Println(err)
	}

	if t.After(time.Now()) {
		return true
	}
	return false
}

func cacheEntryValid(entry charactersResult) bool {
	t, err := time.Parse("2006-01-02 15:04:05", entry.CachedUntil)
	if err != nil {
		fmt.Println(err)
	}

	if t.After(time.Now()) {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package admin

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
)

// FCM type
type FCM struct {
	app    *App
	client *http.Client
}

const (
	fcmSendEndpoint        = "https://fcm.googleapis.com/fcm/send"
	fcmTopicAddEndpoint    = "https://iid.googleapis.com/iid/v1:batchAdd"
	fcmTopicRemoveEndpoint = "https://iid.googleapis.com/iid/v1:batchRemove"
)

func newFCM(app *App) *FCM {
	return &FCM{
		app:    app,
		client: &http.Client{},
	}
}

// SendToDevice Send Message to individual device
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_individual_devices
func (fcm *FCM) SendToDevice(ctx context.Context, registrationToken string, payload Message) (*Response, error) {

	// assign recipient
	payload.To = registrationToken

	// flush other recipients
	payload.RegistrationIDs = nil
	payload.Condition = ""

	// send request to Firebase
	return fcm.sendFirebaseRequest(ctx, payload)
}

// SendToDevices Send multicast Message to a list of devices
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_individual_devices
func (fcm *FCM) SendToDevices(ctx context.Context, registrationTokens []string, payload Message) (*Response, error) {

	// assign recipient
	payload.RegistrationIDs = registrationTokens

	// flush other recipients
	payload.To = ""
	payload.Condition = ""

	// send request to Firebase
	return fcm.sendFirebaseRequest(ctx, payload)
}

// SendToDeviceGroup Send Message to a device group
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_a_device_group
func (fcm *FCM) SendToDeviceGroup(ctx context.Context, notificationKey string, payload Message) (*Response, error) {
	return fcm.SendToDevice(ctx, notificationKey, payload)
}

// SendToTopic Send Message to a topic
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_a_topic
func (fcm *FCM) SendToTopic(ctx context.Context, notificationKey string, payload Message) (*Response, error) {
	return fcm.SendToDevice(ctx, fmt.Sprint("/topic/", notificationKey), payload)
}

// SendToCondition Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_a_condition
func (fcm *FCM) SendToCondition(ctx context.Context, condition string, payload Message) (*Response, error) {

	// assign recipient
	payload.Condition = condition

	// flush other recipients
	payload.To = ""
	payload.RegistrationIDs = nil

	// send request to Firebase
	return fcm.sendFirebaseRequest(ctx, payload)
}

// SubscribeDeviceToTopic subscribe to a device to a topic by providing a registration token for the device to subscribe
// see https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions#subscribe_to_a_topic
func (fcm *FCM) SubscribeDeviceToTopic(ctx context.Context, registrationToken string, topic string) (*Response, error) {
	return fcm.sendFirebaseTopicRequest(ctx, fcmTopicAddEndpoint, Topic{To: topic, RegistrationTokens: []string{registrationToken}})
}

// SubscribeDevicesToTopic subscribe devices to a topic by providing a registrationtokens for the devices to subscribe
// see https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions#subscribe_to_a_topic
func (fcm *FCM) SubscribeDevicesToTopic(ctx context.Context, registrationTokens []string, topic string) (*Response, error) {
	return fcm.sendFirebaseTopicRequest(ctx, fcmTopicAddEndpoint, Topic{To: topic, RegistrationTokens: registrationTokens})
}

// UnSubscribeDeviceFromTopic Unsubscribe a device to a topic by providing a registration token for the device to unsubscribe
// see https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions#unsubscribe_from_a_topic
func (fcm *FCM) UnSubscribeDeviceFromTopic(ctx context.Context, registrationToken string, topic string) (*Response, error) {
	return fcm.sendFirebaseTopicRequest(ctx, fcmTopicRemoveEndpoint, Topic{To: topic, RegistrationTokens: []string{registrationToken}})
}

// UnSubscribeDevicesFromTopic Unsubscribe devices to a topic by providing a registrationtokens for the devices to unsubscribe
// see https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions#unsubscribe_from_a_topic
func (fcm *FCM) UnSubscribeDevicesFromTopic(ctx context.Context, registrationTokens []string, topic string) (*Response, error) {
	return fcm.sendFirebaseTopicRequest(ctx, fcmTopicRemoveEndpoint, Topic{To: topic, RegistrationTokens: registrationTokens})
}

func (fcm *FCM) sendFirebaseRequest(ctx context.Context, payload Message) (*Response, error) {

	// validate Message
	if err := payload.Validate(); err != nil {
		return nil, err
	}

	// marshal message
	data, err := json.Marshal(payload)
	if err != nil {
		return nil, err
	}

	// create request
	req, err := http.NewRequest("POST", fcmSendEndpoint, bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}

	// add context
	req = req.WithContext(ctx)

	// add headers
	req.Header.Set("Authorization", fmt.Sprintf("key=%s", fcm.app.apiKey))
	req.Header.Set("Content-Type", "application/json")

	// execute request
	resp, err := fcm.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {

		switch resp.StatusCode {
		case http.StatusBadRequest:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrInvalidParameters.Error())

		case http.StatusUnauthorized:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrAuthentication.Error())

		case http.StatusInternalServerError:
		default:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrInternalServerError.Error())
		}
	}

	// build response
	response := new(Response)
	if err := json.NewDecoder(resp.Body).Decode(response); err != nil {
		return nil, err
	}

	return response, nil
}

func (fcm *FCM) sendFirebaseTopicRequest(ctx context.Context, endpoint string, payload Topic) (*Response, error) {

	// validate Topic
	if err := payload.Validate(); err != nil {
		return nil, err
	}

	// marshal Topic
	data, err := json.Marshal(payload)
	if err != nil {
		return nil, err
	}

	// create request
	req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}

	// add context
	req = req.WithContext(ctx)

	// add headers
	req.Header.Set("Authorization", fmt.Sprintf("key=%s", fcm.app.apiKey))
	req.Header.Set("Content-Type", "application/json")

	// execute request
	resp, err := fcm.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {

		switch resp.StatusCode {
		case http.StatusBadRequest:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrInvalidParameters.Error())

		case http.StatusUnauthorized:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrAuthentication.Error())

		case http.StatusInternalServerError:
		default:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrInternalServerError.Error())
		}
	}

	// build response
	response := new(Response)
	if err := json.NewDecoder(resp.Body).Decode(response); err != nil {
		return nil, err
	}

	return response, nil
}
<commit_msg>review change marshall by json.NewEncoder + discard resp.body<commit_after>package admin

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
)

// FCM type
type FCM struct {
	app    *App
	client *http.Client
}

const (
	fcmSendEndpoint        = "https://fcm.googleapis.com/fcm/send"
	fcmTopicAddEndpoint    = "https://iid.googleapis.com/iid/v1:batchAdd"
	fcmTopicRemoveEndpoint = "https://iid.googleapis.com/iid/v1:batchRemove"
)

func newFCM(app *App) *FCM {
	return &FCM{
		app:    app,
		client: &http.Client{},
	}
}

// SendToDevice Send Message to individual device
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_individual_devices
func (fcm *FCM) SendToDevice(ctx context.Context, registrationToken string, payload Message) (*Response, error) {

	// assign recipient
	payload.To = registrationToken

	// flush other recipients
	payload.RegistrationIDs = nil
	payload.Condition = ""

	// send request to Firebase
	return fcm.sendFirebaseRequest(ctx, payload)
}

// SendToDevices Send multicast Message to a list of devices
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_individual_devices
func (fcm *FCM) SendToDevices(ctx context.Context, registrationTokens []string, payload Message) (*Response, error) {

	// assign recipient
	payload.RegistrationIDs = registrationTokens

	// flush other recipients
	payload.To = ""
	payload.Condition = ""

	// send request to Firebase
	return fcm.sendFirebaseRequest(ctx, payload)
}

// SendToDeviceGroup Send Message to a device group
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_a_device_group
func (fcm *FCM) SendToDeviceGroup(ctx context.Context, notificationKey string, payload Message) (*Response, error) {
	return fcm.SendToDevice(ctx, notificationKey, payload)
}

// SendToTopic Send Message to a topic
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_a_topic
func (fcm *FCM) SendToTopic(ctx context.Context, notificationKey string, payload Message) (*Response, error) {
	return fcm.SendToDevice(ctx, fmt.Sprint("/topic/", notificationKey), payload)
}

// SendToCondition Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
// see https://firebase.google.com/docs/cloud-messaging/admin/send-messages#send_to_a_condition
func (fcm *FCM) SendToCondition(ctx context.Context, condition string, payload Message) (*Response, error) {

	// assign recipient
	payload.Condition = condition

	// flush other recipients
	payload.To = ""
	payload.RegistrationIDs = nil

	// send request to Firebase
	return fcm.sendFirebaseRequest(ctx, payload)
}

// SubscribeDeviceToTopic subscribe to a device to a topic by providing a registration token for the device to subscribe
// see https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions#subscribe_to_a_topic
func (fcm *FCM) SubscribeDeviceToTopic(ctx context.Context, registrationToken string, topic string) (*Response, error) {
	return fcm.sendFirebaseTopicRequest(ctx, fcmTopicAddEndpoint, Topic{To: topic, RegistrationTokens: []string{registrationToken}})
}

// SubscribeDevicesToTopic subscribe devices to a topic by providing a registrationtokens for the devices to subscribe
// see https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions#subscribe_to_a_topic
func (fcm *FCM) SubscribeDevicesToTopic(ctx context.Context, registrationTokens []string, topic string) (*Response, error) {
	return fcm.sendFirebaseTopicRequest(ctx, fcmTopicAddEndpoint, Topic{To: topic, RegistrationTokens: registrationTokens})
}

// UnSubscribeDeviceFromTopic Unsubscribe a device to a topic by providing a registration token for the device to unsubscribe
// see https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions#unsubscribe_from_a_topic
func (fcm *FCM) UnSubscribeDeviceFromTopic(ctx context.Context, registrationToken string, topic string) (*Response, error) {
	return fcm.sendFirebaseTopicRequest(ctx, fcmTopicRemoveEndpoint, Topic{To: topic, RegistrationTokens: []string{registrationToken}})
}

// UnSubscribeDevicesFromTopic Unsubscribe devices to a topic by providing a registrationtokens for the devices to unsubscribe
// see https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions#unsubscribe_from_a_topic
func (fcm *FCM) UnSubscribeDevicesFromTopic(ctx context.Context, registrationTokens []string, topic string) (*Response, error) {
	return fcm.sendFirebaseTopicRequest(ctx, fcmTopicRemoveEndpoint, Topic{To: topic, RegistrationTokens: registrationTokens})
}

func (fcm *FCM) sendFirebaseRequest(ctx context.Context, payload Message) (*Response, error) {

	// validate Message
	if err := payload.Validate(); err != nil {
		return nil, err
	}

	// Encode Message
	buf := bytes.NewBuffer([]byte{})
	err := json.NewEncoder(buf).Encode(payload)
	if err != nil {
		return nil, err
	}

	// create request
	req, err := http.NewRequest("POST", fcmSendEndpoint, buf)
	if err != nil {
		return nil, err
	}

	// add context
	req = req.WithContext(ctx)

	// add headers
	req.Header.Set("Authorization", fmt.Sprintf("key=%s", fcm.app.apiKey))
	req.Header.Set("Content-Type", "application/json")

	// execute request
	resp, err := fcm.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	defer io.Copy(ioutil.Discard, resp.Body)

	if resp.StatusCode != http.StatusOK {

		switch resp.StatusCode {
		case http.StatusBadRequest:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrInvalidParameters.Error())

		case http.StatusUnauthorized:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrAuthentication.Error())

		case http.StatusInternalServerError:
		default:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrInternalServerError.Error())
		}
	}

	// build response
	response := new(Response)
	if err := json.NewDecoder(resp.Body).Decode(response); err != nil {
		return nil, err
	}

	return response, nil
}

func (fcm *FCM) sendFirebaseTopicRequest(ctx context.Context, endpoint string, payload Topic) (*Response, error) {

	// validate Topic
	if err := payload.Validate(); err != nil {
		return nil, err
	}

	// Encode Topic
	buf := bytes.NewBuffer([]byte{})
	err := json.NewEncoder(buf).Encode(payload)
	if err != nil {
		return nil, err
	}

	// create request
	req, err := http.NewRequest("POST", endpoint, buf)
	if err != nil {
		return nil, err
	}

	// add context
	req = req.WithContext(ctx)

	// add headers
	req.Header.Set("Authorization", fmt.Sprintf("key=%s", fcm.app.apiKey))
	req.Header.Set("Content-Type", "application/json")

	// execute request
	resp, err := fcm.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	defer io.Copy(ioutil.Discard, resp.Body)

	if resp.StatusCode != http.StatusOK {

		switch resp.StatusCode {
		case http.StatusBadRequest:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrInvalidParameters.Error())

		case http.StatusUnauthorized:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrAuthentication.Error())

		case http.StatusInternalServerError:
		default:
			return nil, fmt.Errorf("StatusCode=%d, Desc=%s", resp.StatusCode, ErrInternalServerError.Error())
		}
	}

	// build response
	response := new(Response)
	if err := json.NewDecoder(resp.Body).Decode(response); err != nil {
		return nil, err
	}

	return response, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
)

func main() {
	var des = flag.String("des", "Welcome", "Destination")
	flag.Parse()
	fmt.Println(*des)
}
<commit_msg>FCS removed<commit_after><|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var cmdFix = &Command{
	UsageLine: "fix",
	Short:     "fix the beego application to compatibel with beego 1.6",
	Long: `
As from beego1.6, there's some incompatible code with the old version.

bee fix help to upgrade the application to beego 1.6
`,
}

func init() {
	cmdFix.Run = runFix
}

func runFix(cmd *Command, args []string) int {
	dir, err := os.Getwd()
	if err != nil {
		ColorLog("GetCurrent Path:%s\n", err)
	}
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			if strings.HasPrefix(info.Name(), ".") {
				return filepath.SkipDir
			}
			return nil
		}
		if err != nil {
			return err
		}
		ColorLog("%s\n", path)
		err = fixFile(path)
		if err != nil {
			ColorLog("fixFile:%s\n", err)
		}
		return err
	})
	return 0
}

var rules = []string{
	"beego.AppName", "beego.BConfig.AppName",
	"beego.RunMode", "beego.BConfig.RunMode",
	"beego.RecoverPanic", "beego.BConfig.RecoverPanic",
	"beego.RouterCaseSensitive", "beego.BConfig.RouterCaseSensitive",
	"beego.BeegoServerName", "beego.BConfig.ServerName",
	"beego.EnableGzip", "beego.BConfig.EnableGzip",
	"beego.ErrorsShow", "beego.BConfig.EnableErrorsShow",
	"beego.CopyRequestBody", "beego.BConfig.CopyRequestBody",
	"beego.MaxMemory", "beego.BConfig.MaxMemory",
	"beego.Graceful", "beego.BConfig.Listen.Graceful",
	"beego.HttpAddr", "beego.BConfig.Listen.HTTPAddr",
	"beego.HttpPort", "beego.BConfig.Listen.HTTPPort",
	"beego.ListenTCP4", "beego.BConfig.Listen.ListenTCP4",
	"beego.EnableHttpListen", "beego.BConfig.Listen.HTTPEnable",
	"beego.EnableHttpTLS", "beego.BConfig.Listen.HTTPSEnable",
	"beego.HttpsAddr", "beego.BConfig.Listen.HTTPSAddr",
	"beego.HttpsPort", "beego.BConfig.Listen.HTTPSPort",
	"beego.HttpCertFile", "beego.BConfig.Listen.HTTPSCertFile",
	"beego.HttpKeyFile", "beego.BConfig.Listen.HTTPSKeyFile",
	"beego.EnableAdmin", "beego.BConfig.Listen.AdminEnable",
	"beego.AdminHttpAddr", "beego.BConfig.Listen.AdminAddr",
	"beego.AdminHttpPort", "beego.BConfig.Listen.AdminPort",
	"beego.UseFcgi", "beego.BConfig.Listen.EnableFcgi",
	"beego.HttpServerTimeOut", "beego.BConfig.Listen.ServerTimeOut",
	"beego.AutoRender", "beego.BConfig.WebConfig.AutoRender",
	"beego.ViewsPath", "beego.BConfig.WebConfig.ViewsPath",
	"beego.StaticDir", "beego.BConfig.WebConfig.StaticDir",
	"beego.StaticExtensionsToGzip", "beego.BConfig.WebConfig.StaticExtensionsToGzip",
	"beego.DirectoryIndex", "beego.BConfig.WebConfig.DirectoryIndex",
	"beego.FlashName", "beego.BConfig.WebConfig.FlashName",
	"beego.FlashSeperator", "beego.BConfig.WebConfig.FlashSeperator",
	"beego.EnableDocs", "beego.BConfig.WebConfig.EnableDocs",
	"beego.XSRFKEY", "beego.BConfig.WebConfig.XSRFKEY",
	"beego.EnableXSRF", "beego.BConfig.WebConfig.EnableXSRF",
	"beego.XSRFExpire", "beego.BConfig.WebConfig.XSRFExpire",
	"beego.TemplateLeft", "beego.BConfig.WebConfig.TemplateLeft",
	"beego.TemplateRight", "beego.BConfig.WebConfig.TemplateRight",
	"beego.SessionOn", "beego.BConfig.WebConfig.Session.SessionOn",
	"beego.SessionProvider", "beego.BConfig.WebConfig.Session.SessionProvider",
	"beego.SessionName", "beego.BConfig.WebConfig.Session.SessionName",
	"beego.SessionGCMaxLifetime", "beego.BConfig.WebConfig.Session.SessionGCMaxLifetime",
	"beego.SessionSavePath", "beego.BConfig.WebConfig.Session.SessionProviderConfig",
	"beego.SessionCookieLifeTime", "beego.BConfig.WebConfig.Session.SessionCookieLifeTime",
	"beego.SessionAutoSetCookie", "beego.BConfig.WebConfig.Session.SessionAutoSetCookie",
	"beego.SessionDomain", "beego.BConfig.WebConfig.Session.SessionDomain",
	"Ctx.Input.CopyBody(", "Ctx.Input.CopyBody(beego.BConfig.MaxMemory",
	".UrlFor(", ".URLFor(",
	".ServeJson(", ".ServeJSON(",
	".ServeXml(", ".ServeXML(",
	".XsrfToken(", ".XSRFToken(",
	".CheckXsrfCookie(", ".CheckXSRFCookie(",
	".XsrfFormHtml(", ".XSRFFormHTML(",
	"beego.UrlFor(", "beego.URLFor(",
	"beego.GlobalDocApi", "beego.GlobalDocAPI",
	"beego.Errorhandler", "beego.ErrorHandler",
	"Output.Jsonp(", "Output.JSONP(",
	"Output.Json(", "Output.JSON(",
	"Output.Xml(", "Output.XML(",
	"Input.Uri()", "Input.URI()",
	"Input.Url()", "Input.URL()",
	"Input.AcceptsHtml()", "Input.AcceptsHTML()",
	"Input.AcceptsXml()", "Input.AcceptsXML()",
	"Input.AcceptsJson()", "Input.AcceptsJSON()",
	"Ctx.XsrfToken()", "Ctx.XSRFToken()",
	"Ctx.CheckXsrfCookie()", "Ctx.CheckXSRFCookie()",
	"session.SessionStore", "session.Store",
	".TplNames", ".TplName",
	"swagger.ApiRef", "swagger.APIRef",
	"swagger.ApiDeclaration", "swagger.APIDeclaration",
	"swagger.Api", "swagger.API",
	"swagger.ApiRef", "swagger.APIRef",
	"toolbox.UrlMap", "toolbox.URLMap",
	"logs.LoggerInterface", "logs.Logger",
	"Input.Request", "Input.Context.Request",
	"Input.Params)", "Input.Params())",
	"httplib.BeegoHttpSettings", "httplib.BeegoHTTPSettings",
	"httplib.BeegoHttpRequest", "httplib.BeegoHTTPRequest",
	".TlsClientConfig", ".TLSClientConfig",
	".JsonBody", ".JSONBody",
	".ToJson", ".ToJSON",
	".ToXml", ".ToXML",
	"beego.Html2str", "beego.HTML2str",
	"beego.AssetsCss", "beego.AssetsCSS",
	"orm.DR_Sqlite", "orm.DRSqlite",
	"orm.DR_Postgres", "orm.DRPostgres",
	"orm.DR_MySQL", "orm.DRMySQL",
	"orm.DR_Oracle", "orm.DROracle",
	"orm.Col_Add", "orm.ColAdd",
	"orm.Col_Minus", "orm.ColMinus",
	"orm.Col_Multiply", "orm.ColMultiply",
	"orm.Col_Except", "orm.ColExcept",
	"GenerateOperatorSql", "GenerateOperatorSQL",
	"OperatorSql", "OperatorSQL",
	"orm.Debug_Queries", "orm.DebugQueries",
	"orm.COMMA_SPACE", "orm.CommaSpace",
}

func fixFile(file string) error {
	rp := strings.NewReplacer(rules...)
	content, err := ioutil.ReadFile(file)
	if err != nil {
		return err
	}
	fixed := rp.Replace(string(content))

	// forword the RequestBody from the replace
	// "Input.Request", "Input.Context.Request",
	fixed = strings.Replace(fixed, "Input.Context.RequestBody", "Input.RequestBody", -1)

	// regexp replace
	pareg := regexp.MustCompile(`(Input.Params\[")(.*)("])`)
	fixed = pareg.ReplaceAllString(fixed, "Input.Param(\"$2\")")
	pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])(\s)(=)(\s)(.*)`)
	fixed = pareg.ReplaceAllString(fixed, "Input.SetData(\"$2\", $7)")
	pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])`)
	fixed = pareg.ReplaceAllString(fixed, "Input.Data(\"$2\")")
	// replace the v.Apis in docs.go
	if strings.Contains(file, "docs.go") {
		fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1)
	}

	err = os.Truncate(file, 0)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, []byte(fixed), 0666)
}
<commit_msg>update the fix for config<commit_after>package main

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var cmdFix = &Command{
	UsageLine: "fix",
	Short:     "fix the beego application to compatibel with beego 1.6",
	Long: `
As from beego1.6, there's some incompatible code with the old version.

bee fix help to upgrade the application to beego 1.6
`,
}

func init() {
	cmdFix.Run = runFix
}

func runFix(cmd *Command, args []string) int {
	dir, err := os.Getwd()
	if err != nil {
		ColorLog("GetCurrent Path:%s\n", err)
	}
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			if strings.HasPrefix(info.Name(), ".") {
				return filepath.SkipDir
			}
			return nil
		}
		if err != nil {
			return err
		}
		ColorLog("%s\n", path)
		err = fixFile(path)
		if err != nil {
			ColorLog("fixFile:%s\n", err)
		}
		return err
	})
	return 0
}

var rules = []string{
	"beego.AppName", "beego.BConfig.AppName",
	"beego.RunMode", "beego.BConfig.RunMode",
	"beego.RecoverPanic", "beego.BConfig.RecoverPanic",
	"beego.RouterCaseSensitive", "beego.BConfig.RouterCaseSensitive",
	"beego.BeegoServerName", "beego.BConfig.ServerName",
	"beego.EnableGzip", "beego.BConfig.EnableGzip",
	"beego.ErrorsShow", "beego.BConfig.EnableErrorsShow",
	"beego.CopyRequestBody", "beego.BConfig.CopyRequestBody",
	"beego.MaxMemory", "beego.BConfig.MaxMemory",
	"beego.Graceful", "beego.BConfig.Listen.Graceful",
	"beego.HttpAddr", "beego.BConfig.Listen.HTTPAddr",
	"beego.HttpPort", "beego.BConfig.Listen.HTTPPort",
	"beego.ListenTCP4", "beego.BConfig.Listen.ListenTCP4",
	"beego.EnableHttpListen", "beego.BConfig.Listen.HTTPEnable",
	"beego.EnableHttpTLS", "beego.BConfig.Listen.HTTPSEnable",
	"beego.HttpsAddr", "beego.BConfig.Listen.HTTPSAddr",
	"beego.HttpsPort", "beego.BConfig.Listen.HTTPSPort",
	"beego.HttpCertFile", "beego.BConfig.Listen.HTTPSCertFile",
	"beego.HttpKeyFile", "beego.BConfig.Listen.HTTPSKeyFile",
	"beego.EnableAdmin", "beego.BConfig.Listen.AdminEnable",
	"beego.AdminHttpAddr", "beego.BConfig.Listen.AdminAddr",
	"beego.AdminHttpPort", "beego.BConfig.Listen.AdminPort",
	"beego.UseFcgi", "beego.BConfig.Listen.EnableFcgi",
	"beego.HttpServerTimeOut", "beego.BConfig.Listen.ServerTimeOut",
	"beego.AutoRender", "beego.BConfig.WebConfig.AutoRender",
	"beego.ViewsPath", "beego.BConfig.WebConfig.ViewsPath",
	"beego.StaticDir", "beego.BConfig.WebConfig.StaticDir",
	"beego.StaticExtensionsToGzip", "beego.BConfig.WebConfig.StaticExtensionsToGzip",
	"beego.DirectoryIndex", "beego.BConfig.WebConfig.DirectoryIndex",
	"beego.FlashName", "beego.BConfig.WebConfig.FlashName",
	"beego.FlashSeperator", "beego.BConfig.WebConfig.FlashSeperator",
	"beego.EnableDocs", "beego.BConfig.WebConfig.EnableDocs",
	"beego.XSRFKEY", "beego.BConfig.WebConfig.XSRFKEY",
	"beego.EnableXSRF", "beego.BConfig.WebConfig.EnableXSRF",
	"beego.XSRFExpire", "beego.BConfig.WebConfig.XSRFExpire",
	"beego.TemplateLeft", "beego.BConfig.WebConfig.TemplateLeft",
	"beego.TemplateRight", "beego.BConfig.WebConfig.TemplateRight",
	"beego.SessionOn", "beego.BConfig.WebConfig.Session.SessionOn",
	"beego.SessionProvider", "beego.BConfig.WebConfig.Session.SessionProvider",
	"beego.SessionName", "beego.BConfig.WebConfig.Session.SessionName",
	"beego.SessionGCMaxLifetime", "beego.BConfig.WebConfig.Session.SessionGCMaxLifetime",
	"beego.SessionSavePath", "beego.BConfig.WebConfig.Session.SessionProviderConfig",
	"beego.SessionCookieLifeTime", "beego.BConfig.WebConfig.Session.SessionCookieLifeTime",
	"beego.SessionAutoSetCookie", "beego.BConfig.WebConfig.Session.SessionAutoSetCookie",
	"beego.SessionDomain", "beego.BConfig.WebConfig.Session.SessionDomain",
	"Ctx.Input.CopyBody(", "Ctx.Input.CopyBody(beego.BConfig.MaxMemory",
	".UrlFor(", ".URLFor(",
	".ServeJson(", ".ServeJSON(",
	".ServeXml(", ".ServeXML(",
	".XsrfToken(", ".XSRFToken(",
	".CheckXsrfCookie(", ".CheckXSRFCookie(",
	".XsrfFormHtml(", ".XSRFFormHTML(",
	"beego.UrlFor(", "beego.URLFor(",
	"beego.GlobalDocApi", "beego.GlobalDocAPI",
	"beego.Errorhandler", "beego.ErrorHandler",
	"Output.Jsonp(", "Output.JSONP(",
	"Output.Json(", "Output.JSON(",
	"Output.Xml(", "Output.XML(",
	"Input.Uri()", "Input.URI()",
	"Input.Url()", "Input.URL()",
	"Input.AcceptsHtml()", "Input.AcceptsHTML()",
	"Input.AcceptsXml()", "Input.AcceptsXML()",
	"Input.AcceptsJson()", "Input.AcceptsJSON()",
	"Ctx.XsrfToken()", "Ctx.XSRFToken()",
	"Ctx.CheckXsrfCookie()", "Ctx.CheckXSRFCookie()",
	"session.SessionStore", "session.Store",
	".TplNames", ".TplName",
	"swagger.ApiRef", "swagger.APIRef",
	"swagger.ApiDeclaration", "swagger.APIDeclaration",
	"swagger.Api", "swagger.API",
	"swagger.ApiRef", "swagger.APIRef",
	"toolbox.UrlMap", "toolbox.URLMap",
	"logs.LoggerInterface", "logs.Logger",
	"Input.Request", "Input.Context.Request",
	"Input.Params)", "Input.Params())",
	"httplib.BeegoHttpSettings", "httplib.BeegoHTTPSettings",
	"httplib.BeegoHttpRequest", "httplib.BeegoHTTPRequest",
	".TlsClientConfig", ".TLSClientConfig",
	".JsonBody", ".JSONBody",
	".ToJson", ".ToJSON",
	".ToXml", ".ToXML",
	"beego.Html2str", "beego.HTML2str",
	"beego.AssetsCss", "beego.AssetsCSS",
	"orm.DR_Sqlite", "orm.DRSqlite",
	"orm.DR_Postgres", "orm.DRPostgres",
	"orm.DR_MySQL", "orm.DRMySQL",
	"orm.DR_Oracle", "orm.DROracle",
	"orm.Col_Add", "orm.ColAdd",
	"orm.Col_Minus", "orm.ColMinus",
	"orm.Col_Multiply", "orm.ColMultiply",
	"orm.Col_Except", "orm.ColExcept",
	"GenerateOperatorSql", "GenerateOperatorSQL",
	"OperatorSql", "OperatorSQL",
	"orm.Debug_Queries", "orm.DebugQueries",
	"orm.COMMA_SPACE", "orm.CommaSpace",
}

func fixFile(file string) error {
	rp := strings.NewReplacer(rules...)
	content, err := ioutil.ReadFile(file)
	if err != nil {
		return err
	}
	fixed := rp.Replace(string(content))

	// forword the RequestBody from the replace
	// "Input.Request", "Input.Context.Request",
	fixed = strings.Replace(fixed, "Input.Context.RequestBody", "Input.RequestBody", -1)

	// regexp replace
	pareg := regexp.MustCompile(`(Input.Params\[")(.*)("])`)
	fixed = pareg.ReplaceAllString(fixed, "Input.Param(\"$2\")")
	pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])(\s)(=)(\s)(.*)`)
	fixed = pareg.ReplaceAllString(fixed, "Input.SetData(\"$2\", $7)")
	pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])`)
	fixed = pareg.ReplaceAllString(fixed, "Input.Data(\"$2\")")
	// replace the v.Apis in docs.go
	if strings.Contains(file, "docs.go") {
		fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1)
	}
	// replace the config file
	if strings.HasSuffix(file, ".conf") {
		fixed = strings.Replace(fixed, "HttpCertFile", "HTTPSCertFile", -1)
		fixed = strings.Replace(fixed, "HttpKeyFile", "HTTPSKeyFile", -1)
		fixed = strings.Replace(fixed, "EnableHttpListen", "HTTPEnable", -1)
		fixed = strings.Replace(fixed, "EnableHttpTLS", "EnableHTTPS", -1)
		fixed = strings.Replace(fixed, "EnableHttpTLS", "EnableHTTPS", -1)
		fixed = strings.Replace(fixed, "BeegoServerName", "ServerName", -1)
		fixed = strings.Replace(fixed, "AdminHttpAddr", "AdminAddr", -1)
		fixed = strings.Replace(fixed, "AdminHttpPort", "AdminPort", -1)
		fixed = strings.Replace(fixed, "HttpServerTimeOut", "ServerTimeOut", -1)
	}

	err = os.Truncate(file, 0)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, []byte(fixed), 0666)
}
<|endoftext|>


<commit_before>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package g

import "github.com/gogf/gf/g/container/gvar"

// Universal variable type, like generics.
//
// 动态变量类型，可以用该类型替代interface{}类型
type Var        = gvar.Var

// Frequently-used map type alias.
//
// 常用map数据结构(使用别名)
type Map        = map[interface{}]interface{}
type MapAnyStr  = map[interface{}]string
type MapAnyInt  = map[interface{}]int
type MapStrAny  = map[string]interface{}
type MapStrStr  = map[string]string
type MapStrInt  = map[string]int
type MapIntAny  = map[int]interface{}
type MapIntStr  = map[int]string
type MapIntInt  = map[int]int

// Frequently-used slice type alias.
//
// 常用list数据结构(使用别名)
type List       = []Map
type ListAnyStr = []map[interface{}]string
type ListAnyInt = []map[interface{}]int
type ListStrAny = []map[string]interface{}
type ListStrStr = []map[string]string
type ListStrInt = []map[string]int
type ListIntAny = []map[int]interface{}
type ListIntStr = []map[int]string
type ListIntInt = []map[int]int

// Frequently-used slice type alias.
//
// 常用slice数据结构(使用别名)
type Slice      = []interface{}
type SliceAny   = []interface{}
type SliceStr   = []string
type SliceInt   = []int
type Array      = []interface{}
type ArrayAny   = []interface{}
type ArrayStr   = []string
type ArrayInt   = []int
<commit_msg>revert g.Map to map[string]interface{}, add g.MapAnyAny<commit_after>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package g

import "github.com/gogf/gf/g/container/gvar"

// Universal variable type, like generics.
//
// 动态变量类型，可以用该类型替代interface{}类型
type Var        = gvar.Var

// Frequently-used map type alias.
//
// 常用map数据结构(使用别名)
type Map        = map[string]interface{}
type MapAnyAny  = map[interface{}]interface{}
type MapAnyStr  = map[interface{}]string
type MapAnyInt  = map[interface{}]int
type MapStrAny  = map[string]interface{}
type MapStrStr  = map[string]string
type MapStrInt  = map[string]int
type MapIntAny  = map[int]interface{}
type MapIntStr  = map[int]string
type MapIntInt  = map[int]int

// Frequently-used slice type alias.
//
// 常用list数据结构(使用别名)
type List       = []Map
type ListAnyStr = []map[interface{}]string
type ListAnyInt = []map[interface{}]int
type ListStrAny = []map[string]interface{}
type ListStrStr = []map[string]string
type ListStrInt = []map[string]int
type ListIntAny = []map[int]interface{}
type ListIntStr = []map[int]string
type ListIntInt = []map[int]int

// Frequently-used slice type alias.
//
// 常用slice数据结构(使用别名)
type Slice      = []interface{}
type SliceAny   = []interface{}
type SliceStr   = []string
type SliceInt   = []int
type Array      = []interface{}
type ArrayAny   = []interface{}
type ArrayStr   = []string
type ArrayInt   = []int
<|endoftext|>


<commit_before>package contour

// E versions, these return the error. Non-e versions are just wrapped calls to
// these functions with the error dropped.

// Config Get Methods

// E versions, these return the error. Non-e versions are just wrapped calls to
// these functions with the error dropped.

// GetE returns the setting Value as an interface{}. If its not a valid
// setting, an error is returned.
func (c *Cfg) GetE(k string) (interface{}, error) {
	c.lock.RLock()
	defer c.lock.RUnlock()

	_, ok := c.settings[k]
	if !ok {
		return nil, notFoundErr(k)
	}

	return c.settings[k].Value, nil
}

// GetBoolE returns the setting Value as a bool.
func (c *Cfg) GetBoolE(k string) (string, error) {
	v, err := c.GetE(k)
	if err != nil {
		return "", err
	}

	switch v.(type) {
	case string:
		return v.(string), nil
	case *string:
		return *v.(*string), nil
	}

	// Should never happen, getting here counts as unset
	return "", nil
}

// GetIntE returns the setting Value as an int.
func (c *Cfg) GetIntE(k string) (int, error) {
	v, err := c.GetE(k)
	if err != nil {
		return 0, err
	}

	switch v.(type) {
	case int:
		return v.(int), nil
	case *int:
		return *v.(*int), nil
	}

	return 0, nil
}

// GetInt64E returns the setting Value as an int.
func (c *Cfg) GetInt64E(k string) (int64, error) {
	v, err := c.GetE(k)
	if err != nil {
		return 0, err
	}

	switch v.(type) {
	case int64:
		return v.(int64), nil
	case *int64:
		return *v.(*int64), nil
	}

	return 0, nil
}

// GetStringE returns the setting Value as a string.
func (c *Cfg) GetStringE(k string) (string, error) {
	v, err := c.GetE(k)
	if err != nil {
		return "", err
	}

	switch v.(type) {
	case string:
		return v.(string), nil
	case *string:
		return *v.(*string), nil
	}

	return "", nil
}

// GetInterfaceE is a convenience wrapper function to Get
func (c *Cfg) GetInterfaceE(k string) (interface{}, error) {
	return c.GetE(k)
}

func (c *Cfg) Get(k string) interface{} {
	s, _ := c.GetE(k)
	return s
}

// GetBool returns the setting Value as a bool.
func (c *Cfg) GetBool(k string) string {
	s, _ := c.GetBoolE(k)
	return s
}

// GetInt returns the setting Value as an int.
func (c *Cfg) GetInt(k string) int {
	s, _ := c.GetIntE(k)
	return s
}

// GetInt64 returns the setting Value as an int.
func (c *Cfg) GetInt64(k string) int64 {
	s, _ := c.GetInt64E(k)
	return s
}

// GetString returns the setting Value as a string.
func (c *Cfg) GetString(k string) string {
	s, _ := c.GetStringE(k)
	return s
}

// GetInterfac returns the setting Value as an interface
func (c *Cfg) GetInterface(k string) interface{} {
	return c.Get(k)
}

// Filter Methods obtain a list of flags of the filter type, e.g. boolFilter
// for bool flags, and returns them.
// GetBoolFilterNames returns a list of filter names (flags).
func (c *Cfg) GetBoolFilterNames() []string {
	var names []string

	for k, setting := range c.settings {
		if setting.IsFlag && setting.Type == "bool" {
			names = append(names, k)
		}
	}

	return names
}

// GetIntFilterNames returns a list of filter names (flags).
func (c *Cfg) GetIntFilterNames() []string {
	var names []string

	for k, setting := range c.settings {
		if setting.IsFlag && setting.Type == "int" {
			names = append(names, k)
		}
	}

	return names
}

// GetInt64FilterNames returns a list of filter names (flags).
func (c *Cfg) GetInt64FilterNames() []string {
	var names []string

	for k, setting := range c.settings {
		if setting.IsFlag && setting.Type == "int64" {
			names = append(names, k)
		}
	}

	return names
}

// GetStringFilterNames returns a list of filter names (flags).
func (c *Cfg) GetStringFilterNames() []string {
	var names []string

	for k, setting := range c.settings {
		if setting.IsFlag && setting.Type == "string" {
			names = append(names, k)
		}
	}

	return names
}

// Convenience functions for configs[app]
// Get returns the setting Value as an interface{}.
// GetE returns the setting Value as an interface{}.
func GetE(k string) (interface{}, error) {
	_, ok := appCfg.settings[k]
	if !ok {
		return nil, notFoundErr(k)
	}

	return appCfg.settings[k].Value, nil
}

// GetBoolE returns the setting Value as a bool.
func GetBoolE(k string) (string, error) {
	v, err := GetE(k)
	if err != nil {
		return "", err
	}

	return *v.(*string), nil
}

// GetIntE returns the setting Value as an int.
func GetIntE(k string) (int, error) {
	v, err := GetE(k)
	if err != nil {
		return 0, err
	}

	return *v.(*int), nil
}

// GetInt64E returns the setting Value as an int.
func GetInt64E(k string) (int64, error) {
	v, err := GetE(k)
	if err != nil {
		return 0, err
	}

	return *v.(*int64), nil
}

// GetStringE returns the setting Value as a string.
func GetStringE(k string) (string, error) {
	v, err := GetE(k)
	if err != nil {
		return "", err
	}

	return v.(string), nil
}

// GetInterfaceE is a convenience wrapper function to Get
func GetInterfaceE(k string) (interface{}, error) {
	return appCfg.GetE(k)
}

func Get(k string) interface{} {
	s, _ := appCfg.GetE(k)
	return s
}

// GetBool returns the setting Value as a bool.
func GetBool(k string) string {
	s, _ := appCfg.GetBoolE(k)
	return s
}

// GetInt returns the setting Value as an int.
func GetInt(k string) int {
	s, _ := appCfg.GetIntE(k)
	return s
}

// GetInt64 returns the setting Value as an int.
func GetInt64(k string) int64 {
	s, _ := appCfg.GetInt64E(k)
	return s
}

// GetString returns the setting Value as a string.
func GetString(k string) string {
	s, _ := appCfg.GetStringE(k)
	return s
}

// GetInterface is a convenience wrapper function to Get
func GetInterface(k string) interface{} {
	return appCfg.Get(k)
}

// GetBoolFilterNames returns a list of filter names (flags).
func GetBoolFilterNames() []string {
	var names []string

	for k, setting := range appCfg.settings {
		if setting.IsFlag && setting.Type == "bool" {
			names = append(names, k)
		}
	}

	return names
}

// GetIntFilterNames returns a list of filter names (flags).
func GetIntFilterNames() []string {
	var names []string

	for k, setting := range appCfg.settings {
		if setting.IsFlag && setting.Type == "int" {
			names = append(names, k)
		}
	}

	return names
}

// GetInt64FilterNames returns a list of filter names (flags).
func GetInt64FilterNames() []string {
	var names []string

	for k, setting := range appCfg.settings {
		if setting.IsFlag && setting.Type == "int64" {
			names = append(names, k)
		}
	}

	return names
}

// GetStringFilterNames returns a list of filter names (flags).
func GetStringFilterNames() []string {
	var names []string

	for k, setting := range appCfg.settings {
		if setting.IsFlag && setting.Type == "string" {
			names = append(names, k)
		}
	}

	return names
}
<commit_msg>change GetBool functions to actually return bools. update Get functions to call appCfg instead of having the logic coded within them<commit_after>package contour

import (
	"strconv"
)

// E versions, these return the error. Non-e versions are just wrapped calls to
// these functions with the error dropped.

// Config Get Methods

// E versions, these return the error. Non-e versions are just wrapped calls to
// these functions with the error dropped.

// GetE returns the setting Value as an interface{}. If its not a valid
// setting, an error is returned.
func (c *Cfg) GetE(k string) (interface{}, error) {
	c.lock.RLock()
	defer c.lock.RUnlock()

	_, ok := c.settings[k]
	if !ok {
		return nil, notFoundErr(k)
	}

	return c.settings[k].Value, nil
}

// GetBoolE returns the setting Value as a bool.
func (c *Cfg) GetBoolE(k string) (bool, error) {
	v, err := c.GetE(k)
	if err != nil {
		return false, err
	}

	switch v.(type) {
	case string:
		b, _ := strconv.ParseBool(v.(string))
		return b, nil
	case *string:
		b, _ := strconv.ParseBool(*v.(*string))
		return b, nil
	}

	// Should never happen, getting here counts as unset
	return false, nil
}

// GetIntE returns the setting Value as an int.
func (c *Cfg) GetIntE(k string) (int, error) {
	v, err := c.GetE(k)
	if err != nil {
		return 0, err
	}

	switch v.(type) {
	case int:
		return v.(int), nil
	case *int:
		return *v.(*int), nil
	}

	return 0, nil
}

// GetInt64E returns the setting Value as an int.
func (c *Cfg) GetInt64E(k string) (int64, error) {
	v, err := c.GetE(k)
	if err != nil {
		return 0, err
	}

	switch v.(type) {
	case int64:
		return v.(int64), nil
	case *int64:
		return *v.(*int64), nil
	}

	return 0, nil
}

// GetStringE returns the setting Value as a string.
func (c *Cfg) GetStringE(k string) (string, error) {
	v, err := c.GetE(k)
	if err != nil {
		return "", err
	}

	switch v.(type) {
	case string:
		return v.(string), nil
	case *string:
		return *v.(*string), nil
	}

	return "", nil
}

// GetInterfaceE is a convenience wrapper function to Get
func (c *Cfg) GetInterfaceE(k string) (interface{}, error) {
	return c.GetE(k)
}

func (c *Cfg) Get(k string) interface{} {
	s, _ := c.GetE(k)
	return s
}

// GetBool returns the setting Value as a bool.
func (c *Cfg) GetBool(k string) bool {
	s, _ := c.GetBoolE(k)
	return s
}

// GetInt returns the setting Value as an int.
func (c *Cfg) GetInt(k string) int {
	s, _ := c.GetIntE(k)
	return s
}

// GetInt64 returns the setting Value as an int.
func (c *Cfg) GetInt64(k string) int64 {
	s, _ := c.GetInt64E(k)
	return s
}

// GetString returns the setting Value as a string.
func (c *Cfg) GetString(k string) string {
	s, _ := c.GetStringE(k)
	return s
}

// GetInterfac returns the setting Value as an interface
func (c *Cfg) GetInterface(k string) interface{} {
	return c.Get(k)
}

// Filter Methods obtain a list of flags of the filter type, e.g. boolFilter
// for bool flags, and returns them.
// GetBoolFilterNames returns a list of filter names (flags).
func (c *Cfg) GetBoolFilterNames() []string {
	var names []string

	for k, setting := range c.settings {
		if setting.IsFlag && setting.Type == "bool" {
			names = append(names, k)
		}
	}

	return names
}

// GetIntFilterNames returns a list of filter names (flags).
func (c *Cfg) GetIntFilterNames() []string {
	var names []string

	for k, setting := range c.settings {
		if setting.IsFlag && setting.Type == "int" {
			names = append(names, k)
		}
	}

	return names
}

// GetInt64FilterNames returns a list of filter names (flags).
func (c *Cfg) GetInt64FilterNames() []string {
	var names []string

	for k, setting := range c.settings {
		if setting.IsFlag && setting.Type == "int64" {
			names = append(names, k)
		}
	}

	return names
}

// GetStringFilterNames returns a list of filter names (flags).
func (c *Cfg) GetStringFilterNames() []string {
	var names []string

	for k, setting := range c.settings {
		if setting.IsFlag && setting.Type == "string" {
			names = append(names, k)
		}
	}

	return names
}

// Convenience functions for configs[app]
// Get returns the setting Value as an interface{}.
// GetE returns the setting Value as an interface{}.
func GetE(k string) (interface{}, error) {
	return appCfg.GetE(k)
}

// GetBoolE returns the setting Value as a bool.
func GetBoolE(k string) (bool, error) {
	return appCfg.GetBoolE(k)
}

// GetIntE returns the setting Value as an int.
func GetIntE(k string) (int, error) {
	return appCfg.GetIntE(k)
}

// GetInt64E returns the setting Value as an int.
func GetInt64E(k string) (int64, error) {
	return appCfg.GetInt64E(k)
}

// GetStringE returns the setting Value as a string.
func GetStringE(k string) (string, error) {
	return appCfg.GetStringE(k)
}

// GetInterfaceE is a convenience wrapper function to Get
func GetInterfaceE(k string) (interface{}, error) {
	return appCfg.GetE(k)
}

func Get(k string) interface{} {
	s, _ := appCfg.GetE(k)
	return s
}

// GetBool returns the setting Value as a bool.
func GetBool(k string) bool {
	b, _ := appCfg.GetBoolE(k)
	return b
}

// GetInt returns the setting Value as an int.
func GetInt(k string) int {
	s, _ := appCfg.GetIntE(k)
	return s
}

// GetInt64 returns the setting Value as an int.
func GetInt64(k string) int64 {
	s, _ := appCfg.GetInt64E(k)
	return s
}

// GetString returns the setting Value as a string.
func GetString(k string) string {
	s, _ := appCfg.GetStringE(k)
	return s
}

// GetInterface is a convenience wrapper function to Get
func GetInterface(k string) interface{} {
	return appCfg.Get(k)
}

// GetBoolFilterNames returns a list of filter names (flags).
func GetBoolFilterNames() []string {
	var names []string

	for k, setting := range appCfg.settings {
		if setting.IsFlag && setting.Type == "bool" {
			names = append(names, k)
		}
	}

	return names
}

// GetIntFilterNames returns a list of filter names (flags).
func GetIntFilterNames() []string {
	var names []string

	for k, setting := range appCfg.settings {
		if setting.IsFlag && setting.Type == "int" {
			names = append(names, k)
		}
	}

	return names
}

// GetInt64FilterNames returns a list of filter names (flags).
func GetInt64FilterNames() []string {
	var names []string

	for k, setting := range appCfg.settings {
		if setting.IsFlag && setting.Type == "int64" {
			names = append(names, k)
		}
	}

	return names
}

// GetStringFilterNames returns a list of filter names (flags).
func GetStringFilterNames() []string {
	var names []string

	for k, setting := range appCfg.settings {
		if setting.IsFlag && setting.Type == "string" {
			names = append(names, k)
		}
	}

	return names
}
<|endoftext|>


<commit_before>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package gin

import (
	"github.com/gin-gonic/gin/render"
	"github.com/julienschmidt/httprouter"
	"html/template"
	"math"
	"net/http"
	"sync"
)

const (
	AbortIndex   = math.MaxInt8 / 2
	MIMEJSON     = "application/json"
	MIMEHTML     = "text/html"
	MIMEXML      = "application/xml"
	MIMEXML2     = "text/xml"
	MIMEPlain    = "text/plain"
	MIMEPOSTForm = "application/x-www-form-urlencoded"
)

type (
	HandlerFunc func(*Context)

	// Represents the web framework, it wraps the blazing fast httprouter multiplexer and a list of global middlewares.
	Engine struct {
		*RouterGroup
		HTMLRender     render.Render
		Default404Body []byte
		pool           sync.Pool
		allNoRoute     []HandlerFunc
		noRoute        []HandlerFunc
		router         *httprouter.Router
	}
)

// Returns a new blank Engine instance without any middleware attached.
// The most basic configuration
func New() *Engine {
	engine := &Engine{}
	engine.RouterGroup = &RouterGroup{
		Handlers:     nil,
		absolutePath: "/",
		engine:       engine,
	}
	engine.router = httprouter.New()
	engine.Default404Body = []byte("404 page not found")
	engine.router.NotFound = engine.handle404
	engine.pool.New = func() interface{} {
		c := &Context{Engine: engine}
		c.Writer = &c.writermem
		return c
	}
	return engine
}

// Returns a Engine instance with the Logger and Recovery already attached.
func Default() *Engine {
	engine := New()
	engine.Use(Recovery(), Logger())
	return engine
}

func (engine *Engine) LoadHTMLGlob(pattern string) {
	if IsDebugging() {
		render.HTMLDebug.AddGlob(pattern)
		engine.HTMLRender = render.HTMLDebug
	} else {
		templ := template.Must(template.ParseGlob(pattern))
		engine.SetHTMLTemplate(templ)
	}
}

func (engine *Engine) LoadHTMLFiles(files ...string) {
	if IsDebugging() {
		render.HTMLDebug.AddFiles(files...)
		engine.HTMLRender = render.HTMLDebug
	} else {
		templ := template.Must(template.ParseFiles(files...))
		engine.SetHTMLTemplate(templ)
	}
}

func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
	engine.HTMLRender = render.HTMLRender{
		Template: templ,
	}
}

// Adds handlers for NoRoute. It return a 404 code by default.
func (engine *Engine) NoRoute(handlers ...HandlerFunc) {
	engine.noRoute = handlers
	engine.rebuild404Handlers()
}

func (engine *Engine) Use(middlewares ...HandlerFunc) {
	engine.RouterGroup.Use(middlewares...)
	engine.rebuild404Handlers()
}

func (engine *Engine) rebuild404Handlers() {
	engine.allNoRoute = engine.combineHandlers(engine.noRoute)
}

func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) {
	c := engine.createContext(w, req, nil, engine.allNoRoute)
	// set 404 by default, useful for logging
	c.Writer.WriteHeader(404)
	c.Next()
	if !c.Writer.Written() {
		if c.Writer.Status() == 404 {
			c.Data(-1, MIMEPlain, engine.Default404Body)
		} else {
			c.Writer.WriteHeaderNow()
		}
	}
	engine.reuseContext(c)
}

// ServeHTTP makes the router implement the http.Handler interface.
func (engine *Engine) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	engine.router.ServeHTTP(writer, request)
}

func (engine *Engine) Run(addr string) {
	debugPrint("Listening and serving HTTP on %s", addr)
	if err := http.ListenAndServe(addr, engine); err != nil {
		panic(err)
	}
}

func (engine *Engine) RunTLS(addr string, cert string, key string) {
	debugPrint("Listening and serving HTTPS on %s", addr)
	if err := http.ListenAndServeTLS(addr, cert, key, engine); err != nil {
		panic(err)
	}
}
<commit_msg>Solve #164<commit_after>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package gin

import (
	"github.com/gin-gonic/gin/render"
	"github.com/julienschmidt/httprouter"
	"html/template"
	"math"
	"net/http"
	"sync"
)

const (
	AbortIndex   = math.MaxInt8 / 2
	MIMEJSON     = "application/json"
	MIMEHTML     = "text/html"
	MIMEXML      = "application/xml"
	MIMEXML2     = "text/xml"
	MIMEPlain    = "text/plain"
	MIMEPOSTForm = "application/x-www-form-urlencoded"
)

type (
	HandlerFunc func(*Context)

	// Represents the web framework, it wraps the blazing fast httprouter multiplexer and a list of global middlewares.
	Engine struct {
		*RouterGroup
		HTMLRender     render.Render
		Default404Body []byte
		pool           sync.Pool
		allNoRoute     []HandlerFunc
		noRoute        []HandlerFunc
		router         *httprouter.Router
	}
)

// Returns a new blank Engine instance without any middleware attached.
// The most basic configuration
func New() *Engine {
	engine := &Engine{}
	engine.RouterGroup = &RouterGroup{
		Handlers:     nil,
		absolutePath: "/",
		engine:       engine,
	}
	engine.router = httprouter.New()
	engine.Default404Body = []byte("404 page not found")
	engine.router.NotFound = engine.handle404
	engine.pool.New = func() interface{} {
		c := &Context{Engine: engine}
		c.Writer = &c.writermem
		return c
	}
	return engine
}

// Returns a Engine instance with the Logger and Recovery already attached.
func Default() *Engine {
	engine := New()
	engine.Use(Recovery(), Logger())
	return engine
}

func (engine *Engine) LoadHTMLGlob(pattern string) {
	if IsDebugging() {
		render.HTMLDebug.AddGlob(pattern)
		engine.HTMLRender = render.HTMLDebug
	} else {
		templ := template.Must(template.ParseGlob(pattern))
		engine.SetHTMLTemplate(templ)
	}
}

func (engine *Engine) LoadHTMLFiles(files ...string) {
	if IsDebugging() {
		render.HTMLDebug.AddFiles(files...)
		engine.HTMLRender = render.HTMLDebug
	} else {
		templ := template.Must(template.ParseFiles(files...))
		engine.SetHTMLTemplate(templ)
	}
}

func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
	engine.HTMLRender = render.HTMLRender{
		Template: templ,
	}
}

// Adds handlers for NoRoute. It return a 404 code by default.
func (engine *Engine) NoRoute(handlers ...HandlerFunc) {
	engine.noRoute = handlers
	engine.rebuild404Handlers()
}

func (engine *Engine) Use(middlewares ...HandlerFunc) {
	engine.RouterGroup.Use(middlewares...)
	engine.rebuild404Handlers()
}

func (engine *Engine) rebuild404Handlers() {
	engine.allNoRoute = engine.combineHandlers(engine.noRoute)
}

func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) {
	c := engine.createContext(w, req, nil, engine.allNoRoute)
	// set 404 by default, useful for logging
	c.Writer.WriteHeader(404)
	c.Next()
	if !c.Writer.Written() {
		if c.Writer.Status() == 404 {
			c.Data(-1, MIMEPlain, engine.Default404Body)
		} else {
			c.Writer.WriteHeaderNow()
		}
	}
	engine.reuseContext(c)
}

// ServeHTTP makes the router implement the http.Handler interface.
func (engine *Engine) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	engine.router.ServeHTTP(writer, request)
}

func (engine *Engine) Run(addr string) error {
	debugPrint("Listening and serving HTTP on %s", addr)
	if err := http.ListenAndServe(addr, engine); err != nil {
		return err
	}
	return nil
}

func (engine *Engine) RunTLS(addr string, cert string, key string) error {
	debugPrint("Listening and serving HTTPS on %s", addr)
	if err := http.ListenAndServeTLS(addr, cert, key, engine); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

func gitHost() string {
	if herokuGitHost := os.Getenv("HEROKU_GIT_HOST"); herokuGitHost != "" {
		return herokuGitHost
	}
	if herokuHost := os.Getenv("HEROKU_HOST"); herokuHost != "" {
		return herokuHost
	}
	return "heroku.com"
}

func gitURLPre() string {
	return "git@" + gitHost() + ":"
}

func gitHTTPSURLPre() string {
	return "https://git.heroku.com/"
}

func gitRemotes() (map[string]string, error) {
	b, err := exec.Command("git", "remote", "-v").CombinedOutput()
	if err != nil {
		return nil, errors.New(string(b))
	}

	return parseGitRemoteOutput(b)
}

func appNameFromGitURL(remote string) string {
	switch {
	case strings.HasPrefix(remote, gitHTTPSURLPre()) && strings.HasSuffix(remote, ".git"):
		return remote[len(gitHTTPSURLPre()) : len(remote)-len(".git")]
	case strings.HasPrefix(remote, gitURLPre()) && strings.HasSuffix(remote, ".git"):
		return remote[len(gitURLPre()) : len(remote)-len(".git")]
	default:
		return ""
	}
}

func parseGitRemoteOutput(b []byte) (results map[string]string, err error) {
	s := bufio.NewScanner(bytes.NewBuffer(b))
	s.Split(bufio.ScanLines)

	results = make(map[string]string)

	for s.Scan() {
		by := s.Bytes()
		f := bytes.Fields(by)
		if len(f) != 3 || string(f[2]) != "(push)" {
			// this should have 3 tuples + be a push remote, skip it if not
			continue
		}

		if appName := appNameFromGitURL(string(f[1])); appName != "" {
			results[string(f[0])] = appName
		}
	}
	if err = s.Err(); err != nil {
		return nil, err
	}
	return
}

func remoteFromGitConfig() string {
	b, err := exec.Command("git", "config", "heroku.remote").Output()
	if err != nil {
		return ""
	}
	return strings.TrimSpace(string(b))
}

func errMultipleHerokuRemotes(remotes []string) error {
	return errors.New("multiple apps in git remotes\nremotes: " + strings.Join(remotes, " "))
}

func appFromGitRemote(remote string) (string, error) {
	if remote != "" {
		b, err := exec.Command("git", "config", "remote."+remote+".url").Output()
		if err != nil {
			if isNotFound(err) {
				wdir, _ := os.Getwd()
				remotes, err := gitRemotes()
				if err != nil {
					return "", err
				}
				return "", fmt.Errorf("could not find git remote "+remote+" in %s\nremotes: %s", wdir, strings.Join(mapKeys(remotes), " "))
			}
			return "", err
		}

		out := strings.TrimSpace(string(b))

		appName := appNameFromGitURL(out)
		if appName == "" {
			return "", fmt.Errorf("could not find app name in " + remote + " git remote")
		}
		return appName, nil
	}

	// no remote specified, see if there is a single Heroku app remote
	remotes, err := gitRemotes()
	if err != nil {
		return "", nil // hide this error
	}
	remoteValues := uniqueMapValues(remotes)
	if len(remoteValues) > 1 {
		return "", errMultipleHerokuRemotes(mapKeys(remotes))
	}
	for _, v := range remotes {
		return v, nil
	}
	return "", nil
}

func uniqueMapValues(m map[string]string) []string {
	n := make([]string, 0, len(m))
	ref := make(map[string]bool, len(m))
	for _, v := range m {
		if _, ok := ref[v]; !ok {
			ref[v] = true
			n = append(n, v)
		}
	}
	return n
}

func mapKeys(m map[string]string) []string {
	n := make([]string, 0, len(m))
	for k := range m {
		n = append(n, k)
	}
	return n
}

func isNotFound(err error) bool {
	if ee, ok := err.(*exec.ExitError); ok {
		if ws, ok := ee.ProcessState.Sys().(syscall.WaitStatus); ok {
			return ws.ExitStatus() == 1
		}
	}
	return false
}
<commit_msg>only list remotes if there are any<commit_after>package main

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

func gitHost() string {
	if herokuGitHost := os.Getenv("HEROKU_GIT_HOST"); herokuGitHost != "" {
		return herokuGitHost
	}
	if herokuHost := os.Getenv("HEROKU_HOST"); herokuHost != "" {
		return herokuHost
	}
	return "heroku.com"
}

func gitURLPre() string {
	return "git@" + gitHost() + ":"
}

func gitHTTPSURLPre() string {
	return "https://git.heroku.com/"
}

func gitRemotes() (map[string]string, error) {
	b, err := exec.Command("git", "remote", "-v").CombinedOutput()
	if err != nil {
		return nil, errors.New(string(b))
	}

	return parseGitRemoteOutput(b)
}

func appNameFromGitURL(remote string) string {
	switch {
	case strings.HasPrefix(remote, gitHTTPSURLPre()) && strings.HasSuffix(remote, ".git"):
		return remote[len(gitHTTPSURLPre()) : len(remote)-len(".git")]
	case strings.HasPrefix(remote, gitURLPre()) && strings.HasSuffix(remote, ".git"):
		return remote[len(gitURLPre()) : len(remote)-len(".git")]
	default:
		return ""
	}
}

func parseGitRemoteOutput(b []byte) (results map[string]string, err error) {
	s := bufio.NewScanner(bytes.NewBuffer(b))
	s.Split(bufio.ScanLines)

	results = make(map[string]string)

	for s.Scan() {
		by := s.Bytes()
		f := bytes.Fields(by)
		if len(f) != 3 || string(f[2]) != "(push)" {
			// this should have 3 tuples + be a push remote, skip it if not
			continue
		}

		if appName := appNameFromGitURL(string(f[1])); appName != "" {
			results[string(f[0])] = appName
		}
	}
	if err = s.Err(); err != nil {
		return nil, err
	}
	return
}

func remoteFromGitConfig() string {
	b, err := exec.Command("git", "config", "heroku.remote").Output()
	if err != nil {
		return ""
	}
	return strings.TrimSpace(string(b))
}

func errMultipleHerokuRemotes(remotes []string) error {
	return errors.New("multiple apps in git remotes\nremotes: " + strings.Join(remotes, " "))
}

func appFromGitRemote(remote string) (string, error) {
	if remote != "" {
		b, err := exec.Command("git", "config", "remote."+remote+".url").Output()
		if err != nil {
			if isNotFound(err) {
				wdir, _ := os.Getwd()
				remotes, err := gitRemotes()
				if err != nil {
					return "", err
				}
				msg := fmt.Sprintf("could not find git remote %s in %s", remote, wdir)
				if len(remotes) != 0 {
					msg = fmt.Sprintf("%s\nremotes: %s", msg, strings.Join(mapKeys(remotes), " "))
				}
				return "", errors.New(msg)
			}
			return "", err
		}

		out := strings.TrimSpace(string(b))

		appName := appNameFromGitURL(out)
		if appName == "" {
			return "", fmt.Errorf("could not find app name in " + remote + " git remote")
		}
		return appName, nil
	}

	// no remote specified, see if there is a single Heroku app remote
	remotes, err := gitRemotes()
	if err != nil {
		return "", nil // hide this error
	}
	remoteValues := uniqueMapValues(remotes)
	if len(remoteValues) > 1 {
		return "", errMultipleHerokuRemotes(mapKeys(remotes))
	}
	for _, v := range remotes {
		return v, nil
	}
	return "", nil
}

func uniqueMapValues(m map[string]string) []string {
	n := make([]string, 0, len(m))
	ref := make(map[string]bool, len(m))
	for _, v := range m {
		if _, ok := ref[v]; !ok {
			ref[v] = true
			n = append(n, v)
		}
	}
	return n
}

func mapKeys(m map[string]string) []string {
	n := make([]string, 0, len(m))
	for k := range m {
		n = append(n, k)
	}
	return n
}

func isNotFound(err error) bool {
	if ee, ok := err.(*exec.ExitError); ok {
		if ws, ok := ee.ProcessState.Sys().(syscall.WaitStatus); ok {
			return ws.ExitStatus() == 1
		}
	}
	return false
}
<|endoftext|>


<commit_before>package dao

import (
	"math"
)

// H1D is a 1-dim histogram with weighted entries.
type H1D struct {
	bins    []Bin1D // in-range bins
	allbins []Bin1D // in-range bins and under/over-flow bins
	axis    Axis
	entries int64      // number of entries for this histogram
	ann     Annotation // Annotations for this histogram (title, labels,...)
}

// NewH1D returns a 1-dim histogram with nbins bins between low and high.
func NewH1D(nbins int, low, high float64) *H1D {
	h := &H1D{
		bins:    nil,
		allbins: make([]Bin1D, nbins+2),
		axis:    NewEvenBinAxis(nbins, low, high),
		entries: 0,
		ann:     make(Annotation),
	}
	h.bins = h.allbins[2:]
	return h
}

// Name returns the name of this histogram, if any
func (h *H1D) Name() string {
	n := h.ann["name"].(string)
	return n
}

// Annotation returns the annotations attached to this histogram
func (h *H1D) Annotation() Annotation {
	return h.ann
}

// Rank returns the number of dimensions for this histogram
func (h *H1D) Rank() int {
	return 1
}

// Axis returns the axis of this histgram.
func (h *H1D) Axis() Axis {
	return h.axis
}

// Entries returns the number of entries in this histogram
func (h *H1D) Entries() int64 {
	return h.entries
}

// Fill fills this histogram with x and weight w.
func (h *H1D) Fill(x, w float64) {
	//fmt.Printf("H1D.fill(x=%v, w=%v)...\n", x, w)
	idx := h.axis.CoordToIndex(x)
	switch idx {
	case UnderflowBin:
		h.allbins[0].fill(x, w)
	case OverflowBin:
		h.allbins[1].fill(x, w)
	default:
		h.bins[idx].fill(x, w)
	}
	h.entries += 1
	//fmt.Printf("H1D.fill(x=%v, w=%v)...[done]\n", x, w)
}

// Content returns the content of the idx-th bin.
func (h *H1D) Content(idx int) float64 {
	return h.bins[idx].sw
}

// Mean returns the mean of this histogram.
func (h *H1D) Mean() float64 {
	summeans := 0.0
	sumweights := 0.0
	idx := 0
	for idx = 0; idx < len(h.bins); idx++ {
		summeans = summeans + h.bins[idx].swc
		sumweights = sumweights + h.bins[idx].sw
	}
	return summeans / sumweights
}

// RMS returns the root mean squared of this histogram.
func (h *H1D) RMS() float64 {
	summeans := 0.0
	summean2 := 0.0
	sumweights := 0.0
	idx := 0
	for idx = 0; idx < len(h.bins); idx++ {
		summeans = summeans + h.bins[idx].swc
		sumweights = sumweights + h.bins[idx].sw
		if h.bins[idx].sw != 0. {
			summean2 = summean2 + h.bins[idx].swc*h.bins[idx].swc/h.bins[idx].sw
		}
	}
	invw := 1. / sumweights
	return math.Sqrt(invw * (summean2 - (summeans*summeans)*invw))
}

// Max returns the maximum y value of this histogram.
func (h *H1D) Max() float64 {
	ymax := math.Inf(-1)
	for idx := range h.bins {
		c := h.bins[idx].sw
		if c > ymax {
			ymax = c
		}
	}
	return ymax
}

// Min returns the minimum y value of this histogram.
func (h *H1D) Min() float64 {
	ymin := math.Inf(1)
	for idx := range h.bins {
		c := h.bins[idx].sw
		if c < ymin {
			ymin = c
		}
	}
	return ymin
}

// check various interfaces
var _ Histogram = (*H1D)(nil)

// EOF
<commit_msg>h1d: test dao.Object interface<commit_after>package dao

import (
	"math"
)

// H1D is a 1-dim histogram with weighted entries.
type H1D struct {
	bins    []Bin1D // in-range bins
	allbins []Bin1D // in-range bins and under/over-flow bins
	axis    Axis
	entries int64      // number of entries for this histogram
	ann     Annotation // Annotations for this histogram (title, labels,...)
}

// NewH1D returns a 1-dim histogram with nbins bins between low and high.
func NewH1D(nbins int, low, high float64) *H1D {
	h := &H1D{
		bins:    nil,
		allbins: make([]Bin1D, nbins+2),
		axis:    NewEvenBinAxis(nbins, low, high),
		entries: 0,
		ann:     make(Annotation),
	}
	h.bins = h.allbins[2:]
	return h
}

// Name returns the name of this histogram, if any
func (h *H1D) Name() string {
	n := h.ann["name"].(string)
	return n
}

// Annotation returns the annotations attached to this histogram
func (h *H1D) Annotation() Annotation {
	return h.ann
}

// Rank returns the number of dimensions for this histogram
func (h *H1D) Rank() int {
	return 1
}

// Axis returns the axis of this histgram.
func (h *H1D) Axis() Axis {
	return h.axis
}

// Entries returns the number of entries in this histogram
func (h *H1D) Entries() int64 {
	return h.entries
}

// Fill fills this histogram with x and weight w.
func (h *H1D) Fill(x, w float64) {
	//fmt.Printf("H1D.fill(x=%v, w=%v)...\n", x, w)
	idx := h.axis.CoordToIndex(x)
	switch idx {
	case UnderflowBin:
		h.allbins[0].fill(x, w)
	case OverflowBin:
		h.allbins[1].fill(x, w)
	default:
		h.bins[idx].fill(x, w)
	}
	h.entries += 1
	//fmt.Printf("H1D.fill(x=%v, w=%v)...[done]\n", x, w)
}

// Content returns the content of the idx-th bin.
func (h *H1D) Content(idx int) float64 {
	return h.bins[idx].sw
}

// Mean returns the mean of this histogram.
func (h *H1D) Mean() float64 {
	summeans := 0.0
	sumweights := 0.0
	idx := 0
	for idx = 0; idx < len(h.bins); idx++ {
		summeans = summeans + h.bins[idx].swc
		sumweights = sumweights + h.bins[idx].sw
	}
	return summeans / sumweights
}

// RMS returns the root mean squared of this histogram.
func (h *H1D) RMS() float64 {
	summeans := 0.0
	summean2 := 0.0
	sumweights := 0.0
	idx := 0
	for idx = 0; idx < len(h.bins); idx++ {
		summeans = summeans + h.bins[idx].swc
		sumweights = sumweights + h.bins[idx].sw
		if h.bins[idx].sw != 0. {
			summean2 = summean2 + h.bins[idx].swc*h.bins[idx].swc/h.bins[idx].sw
		}
	}
	invw := 1. / sumweights
	return math.Sqrt(invw * (summean2 - (summeans*summeans)*invw))
}

// Max returns the maximum y value of this histogram.
func (h *H1D) Max() float64 {
	ymax := math.Inf(-1)
	for idx := range h.bins {
		c := h.bins[idx].sw
		if c > ymax {
			ymax = c
		}
	}
	return ymax
}

// Min returns the minimum y value of this histogram.
func (h *H1D) Min() float64 {
	ymin := math.Inf(1)
	for idx := range h.bins {
		c := h.bins[idx].sw
		if c < ymin {
			ymin = c
		}
	}
	return ymin
}

// check various interfaces
var _ Object = (*H1D)(nil)
var _ Histogram = (*H1D)(nil)

// EOF
<|endoftext|>


<commit_before>// Copyright 2014 Nicolas Vellon.  All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package hal implements encoding of structs into HAL as defined in
// http://stateless.co/hal_specification.html.
//
// See the basic example for an introduction to this package:
// https://github.com/nvellon/hal/blob/master/examples/basic.go

package hal

import (
	"encoding/json"
)

type (
	Entry map[string]interface{}

	// Mapper is the interface implemented by the objects
	// that can be converted into HAL format.
	Mapper interface {
		GetMap() Entry
	}

	Relation string

	// Link types that store hyperlinks and its attributes.
	LinkAttr       map[string]string
	Link           LinkAttr
	LinkCollection []Link
	LinkRelations  map[Relation]LinkCollection

	// Resource is a struct that stores a resource data.
	// It represents a converted object in the HAL spec by
	// containing all its fields and also a set of related links
	// and a sub-set of recursively related resources.
	Resource struct {
		Payload  Mapper
		Links    LinkRelations
		Embedded Embedded
	}

	Embedded map[Relation][]*Resource
)

// Add appends the resource into the list of embedded
// resources with the specified relation.
func (e Embedded) Add(rel Relation, r *Resource) {
	e[rel] = append(e[rel], r)
}

// Set sets the resource into the list of embedded
// resources with the specified relation. It replaces
// any existing resources associated with the relation.
func (e Embedded) Set(rel Relation, r *Resource) {
	e[rel] = []*Resource{r}
}

// Get gets the resources associated with the
// given relation.
func (e Embedded) Get(rel Relation) []*Resource {
	return e[rel]
}

// Del deletes the resources associated with the
// given relation.
func (e Embedded) Del(rel Relation) {
	delete(e, rel)
}

// NewResource creates a Resource object for a given struct
// and its link.
func NewResource(p Mapper, selfUri string) *Resource {
	var r Resource

	r.Payload = p

	r.Links = make(LinkRelations)
	r.AddNewLink("self", selfUri)

	r.Embedded = make(Embedded)

	return &r
}

// AddLink appends a Link to the resource.
func (r *Resource) AddLink(rel Relation, l Link) {
	r.Links[rel] = append(r.Links[rel], l)
}

// AddNewLink appends a new Link object based on
// the rel and href params.
func (r *Resource) AddNewLink(rel Relation, href string) {
	r.AddLink(rel, NewLink(href, nil))
}

// Embed appends a Resource to the array of
// embedded resources.
func (r *Resource) Embed(rel Relation, er *Resource) {
	r.Embedded.Add(rel, er)
}

// Map implements the interface Mapper.
func (r Resource) GetMap() Entry {
	mapped := make(Entry)

	mp := r.Payload.GetMap()

	for k, v := range mp {
		mapped[k] = v
	}

	mapped["_links"] = r.Links

	if len(r.Embedded) > 0 {
		mapped["_embedded"] = r.Embedded
	}

	return mapped
}

// MarshalJSON is a Marshaler interface implementation
// for Resource struct
func (r Resource) MarshalJSON() ([]byte, error) {
	return json.Marshal(r.GetMap())
}

// NewLink returns a new Link object.
func NewLink(href string, attr LinkAttr) Link {
	l := make(Link)

	l["href"] = href

	for k, v := range attr {
		l[k] = v
	}

	return l
}
<commit_msg>support single links, resources as well as slices (including single slice)<commit_after>// Copyright 2014 Nicolas Vellon.  All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package hal implements encoding of structs into HAL as defined in
// http://stateless.co/hal_specification.html.
//
// See the basic example for an introduction to this package:
// https://github.com/nvellon/hal/blob/master/examples/basic.go

package hal

import (
	"encoding/json"
)

type (
	Entry map[string]interface{}

	// Mapper is the interface implemented by the objects
	// that can be converted into HAL format.
	Mapper interface {
		GetMap() Entry
	}

	Relation string

	// Link types that store hyperlinks and its attributes.
	LinkAttr           map[string]string
	Link               LinkAttr
	LinkCollection     []Link
	ResourceCollection []*Resource
	LinkRelations      map[Relation]interface{}

	// Resource is a struct that stores a resource data.
	// It represents a converted object in the HAL spec by
	// containing all its fields and also a set of related links
	// and a sub-set of recursively related resources.
	Resource struct {
		Payload  Mapper
		Links    LinkRelations
		Embedded Embedded
	}

	Embedded map[Relation]interface{}
)

// AddCollection appends the resource into the list of embedded
// resources with the specified relation.
// r should be  a ResourceCollection
func (e Embedded) AddCollection(rel Relation, r ResourceCollection) {
	n := e[rel]
	if n == nil {
		//new embed
		e[rel] = r
		return
	}

	nr, isExistingResource := n.(*Resource)
	nc, isExistingCollection := n.([]*Resource)

	if isExistingCollection {
		//existing collection
		e[rel] = append(nc, r...)
		return
	}

	if isExistingResource {
		//single resource - turn it into a collection
		e[rel] = append([]*Resource{nr}, r...)
	}

}

// Add appends the resource into the list of embedded
// resources with the specified relation.
// r should be a Resource
func (e Embedded) Add(rel Relation, r *Resource) {
	n := e[rel]
	if n == nil {
		//new embed
		e[rel] = r
		return
	}

	nee, isExistingResource := n.(*Resource)
	nec, isExistingCollection := n.([]*Resource)

	if isExistingCollection {
		//existing collection
		nec = append(nec, r)
		e[rel] = nec
		return
	}

	if isExistingResource {
		//existing resource with same rel - turn it into a collection
		resources := []*Resource{nee}
		resources = append(resources, r)
		e[rel] = resources
	} else {
		//something went wrong.. replace what is there with what is new
		resources := []*Resource{r}
		e[rel] = resources
	}
}

// Set sets the resource into the list of embedded
// resources with the specified relation. It replaces
// any existing resources associated with the relation.
// r should be a pointer to a Resource
func (e Embedded) Set(rel Relation, r *Resource) {
	e[rel] = r
}

// Set sets the resource into the list of embedded
// resources with the specified relation. It replaces
// any existing resources associated with the relation.
// r should be a ResourceCollection
func (e Embedded) SetCollection(rel Relation, r ResourceCollection) {
	e[rel] = r
}

// Get gets the resources associated with the
// given relation.
//func (e Embedded) Get(rel Relation) []*Resource {
//	return e[rel]
//}

// Del deletes the resources associated with the
// given relation.
func (e Embedded) Del(rel Relation) {
	delete(e, rel)
}

// NewResource creates a Resource object for a given struct
// and its link.
func NewResource(p Mapper, selfUri string) *Resource {
	var r Resource

	r.Payload = p

	r.Links = make(LinkRelations)
	r.AddNewLink("self", selfUri)

	r.Embedded = make(Embedded)

	return &r
}

// AddLinkCollection appends a LinkCollection to the resource.
// l should be a LinkCollection
func (r *Resource) AddLinkCollection(rel Relation, l LinkCollection) {
	n := r.Links[rel]
	if n == nil {
		//new link
		r.Links[rel] = l
		return
	}

	nl, isExistingLink := n.(Link)
	nc, isExistingCollection := n.(LinkCollection)

	if isExistingCollection {
		//existing collection
		r.Links[rel] = append(nc, l...)
		return
	}

	if isExistingLink {
		//prepend existing link to collection
		r.Links[rel] = append(LinkCollection{nl}, l...)
	}

}

// AddLink appends a Link to the resource.
// l should be a Link
func (r *Resource) AddLink(rel Relation, l Link) {
	n := r.Links[rel]
	if n == nil {
		//new link
		r.Links[rel] = l
		return
	}

	nl, isExistingLink := n.(Link)
	nc, isExistingCollection := n.(LinkCollection)

	if isExistingCollection {
		//existing collection
		nc = append(nc, l)
		r.Links[rel] = nc
		return
	}

	if isExistingLink {
		//existing link with same rel - turn it into a collection
		r.Links[rel] = append(LinkCollection{nl}, l)
	} else {
		//something went wrong.. replace what is there with what is new
		r.Links[rel] = LinkCollection{l}
	}
}

// AddNewLink appends a new Link object based on
// the rel and href params.
func (r *Resource) AddNewLink(rel Relation, href string) {
	r.AddLink(rel, NewLink(href, nil))
}

// Embed appends a Resource to the array of
// embedded resources.
// re should be a pointer to a Resource
func (r *Resource) Embed(rel Relation, re *Resource) {
	r.Embedded.Add(rel, re)
}

// EmbedCollection appends a ResourceCollection to the array of
// embedded resources.
// re should be a ResourceCollection
func (r *Resource) EmbedCollection(rel Relation, re ResourceCollection) {
	r.Embedded.AddCollection(rel, re)
}

// Map implements the interface Mapper.
func (r Resource) GetMap() Entry {
	mapped := make(Entry)

	mp := r.Payload.GetMap()

	for k, v := range mp {
		mapped[k] = v
	}

	mapped["_links"] = r.Links

	if len(r.Embedded) > 0 {
		mapped["_embedded"] = r.Embedded
	}

	return mapped
}

// MarshalJSON is a Marshaler interface implementation
// for Resource struct
func (r Resource) MarshalJSON() ([]byte, error) {
	return json.Marshal(r.GetMap())
}

// NewLink returns a new Link object.
func NewLink(href string, attr LinkAttr) Link {
	l := make(Link)

	l["href"] = href

	for k, v := range attr {
		l[k] = v
	}

	return l
}
<|endoftext|>