github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/action_getlinks.go (about)

     1  package holochain
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	. "github.com/holochain/holochain-proto/hash"
     7  	peer "github.com/libp2p/go-libp2p-peer"
     8  	"reflect"
     9  )
    10  
    11  //------------------------------------------------------------
    12  // GetLinks
    13  
    14  type APIFnGetLinks struct {
    15  	action ActionGetLinks
    16  }
    17  
    18  func (fn *APIFnGetLinks) Name() string {
    19  	return fn.action.Name()
    20  }
    21  
    22  func (fn *APIFnGetLinks) Args() []Arg {
    23  	return []Arg{{Name: "base", Type: HashArg}, {Name: "tag", Type: StringArg}, {Name: "options", Type: MapArg, MapType: reflect.TypeOf(GetLinksOptions{}), Optional: true}}
    24  }
    25  
    26  func (fn *APIFnGetLinks) Call(h *Holochain) (response interface{}, err error) {
    27  	var r interface{}
    28  	a := &fn.action
    29  	r, err = h.dht.Query(a.linkQuery.Base, GETLINK_REQUEST, *a.linkQuery)
    30  
    31  	if err == nil {
    32  		switch t := r.(type) {
    33  		case *LinkQueryResp:
    34  			response = t
    35  			if a.options.Load {
    36  				for i := range t.Links {
    37  					var hash Hash
    38  					hash, err = NewHash(t.Links[i].H)
    39  					if err != nil {
    40  						return
    41  					}
    42  					opts := GetOptions{GetMask: GetMaskEntryType + GetMaskEntry, StatusMask: StatusDefault}
    43  					req := GetReq{H: hash, StatusMask: StatusDefault, GetMask: opts.GetMask}
    44  					var rsp interface{}
    45  					rsp, err = callGet(h, req, &opts)
    46  					if err == nil {
    47  						// TODO: bleah, really this should be another of those
    48  						// case statements that choses the encoding baste on
    49  						// entry type, time for a refactor!
    50  						entry := rsp.(GetResp).Entry
    51  						switch content := entry.Content().(type) {
    52  						case string:
    53  							t.Links[i].E = content
    54  						case []byte:
    55  							var j []byte
    56  							j, err = json.Marshal(content)
    57  							if err != nil {
    58  								return
    59  							}
    60  							t.Links[i].E = string(j)
    61  						default:
    62  							err = fmt.Errorf("bad type in entry content: %T:%v", content, content)
    63  						}
    64  						t.Links[i].EntryType = rsp.(GetResp).EntryType
    65  					}
    66  					//TODO better error handling here, i.e break out of the loop and return if error?
    67  				}
    68  			}
    69  		default:
    70  			err = fmt.Errorf("unexpected response type from SendGetLinks: %T", t)
    71  		}
    72  	}
    73  	return
    74  }
    75  
    76  type ActionGetLinks struct {
    77  	linkQuery *LinkQuery
    78  	options   *GetLinksOptions
    79  }
    80  
    81  func NewGetLinksAction(linkQuery *LinkQuery, options *GetLinksOptions) *ActionGetLinks {
    82  	a := ActionGetLinks{linkQuery: linkQuery, options: options}
    83  	return &a
    84  }
    85  
    86  func (a *ActionGetLinks) Name() string {
    87  	return "getLinks"
    88  }
    89  
    90  func (a *ActionGetLinks) SysValidation(h *Holochain, d *EntryDef, pkg *Package, sources []peer.ID) (err error) {
    91  	//@TODO what sys level getlinks validation?  That they are all valid hash format for the DNA?
    92  	return
    93  }
    94  
    95  func (a *ActionGetLinks) Receive(dht *DHT, msg *Message) (response interface{}, err error) {
    96  	lq := msg.Body.(LinkQuery)
    97  	var r LinkQueryResp
    98  	r.Links, err = dht.GetLinks(lq.Base, lq.T, lq.StatusMask)
    99  	response = &r
   100  
   101  	return
   102  }