func (obd OperationData) GetID() string {
	b := bytes.Buffer{}
	b.WriteString(obd.Type)
	b.WriteString("/")
	b.WriteString(obd.ID)
	return b.String()
}
GetID returns the operation id
package oplog
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"strings"
	"time"
	"gopkg.in/mgo.v2/bson"
)
type Operation struct {
	ID    *bson.ObjectId `bson:"_id,omitempty"`
	Event string         `bson:"event"`
	Data  *OperationData `bson:"data"`
}
type OperationData struct {
	Timestamp time.Time `bson:"ts" json:"timestamp"`
	Parents   []string  `bson:"p" json:"parents"`
	Type      string    `bson:"t" json:"type"`
	ID        string    `bson:"id" json:"id"`
	Ref       string    `bson:"-,omitempty" json:"ref,omitempty"`
}
func NewOperation(event string, time time.Time, objID, objType string, objParents []string) *Operation {
	id := bson.NewObjectId()
	return &Operation{
		ID:    &id,
		Event: event,
		Data: &OperationData{
			Timestamp: time,
			ID:        objID,
			Type:      objType,
			Parents:   objParents,
		},
	}
}
func (op Operation) GetEventID() LastID {
	return &OperationLastID{op.ID}
}
func (op Operation) Validate() error {
	switch op.Event {
	case "insert", "update", "delete":
	default:
		return fmt.Errorf("invalid event name: %s", op.Event)
	}
	return op.Data.Validate()
}
func (op Operation) WriteTo(w io.Writer) (int64, error) {
	data, err := json.Marshal(op.Data)
	if err != nil {
		return 0, err
	}
	n, err := fmt.Fprintf(w, "id: %s\nevent: %s\ndata: %s\n\n", op.ID.Hex(), op.Event, data)
	return int64(n), err
}
func (op *Operation) Info() string {
	id := "(new)"
	if op.ID != nil {
		id = op.ID.Hex()
	}
	return fmt.Sprintf("%s:%s(%s:%s)", id, op.Event, op.Data.Type, op.Data.ID)
}
func (obd *OperationData) genRef(objectURL string) {
	if objectURL == "" {
		obd.Ref = ""
		return
	}
	r := strings.NewReplacer("{{type}}", obd.Type, "{{id}}", obd.ID)
	obd.Ref = r.Replace(objectURL)
}