github.com/weaviate/weaviate@v1.24.6/entities/schema/crossref/crossref.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package crossref 13 14 import ( 15 "fmt" 16 "net/url" 17 "strings" 18 19 "github.com/go-openapi/strfmt" 20 "github.com/weaviate/weaviate/entities/models" 21 ) 22 23 const ( 24 _LocalHost = "localhost" 25 _Schema = "weaviate" 26 ) 27 28 // Ref is an abstraction of the cross-refs which are specified in a URI format 29 // in the API. When this type is used it is safe to assume that a Ref is 30 // semantically valid. This guarantee would not be possible on the URI format, 31 // as the URI can be well-formed, but not contain the data we expect in it. 32 // Do not use directly, such as crossref.Ref{}, as you won't have any 33 // guarantees in this case. Always use one of the parsing options or New() 34 type Ref struct { 35 Local bool `json:"local"` 36 PeerName string `json:"peerName"` 37 TargetID strfmt.UUID `json:"targetID"` 38 Class string `json:"className"` 39 } 40 41 // Parse is a safe way to generate a Ref, as it will error if any of the input 42 // parameters are not as expected. 43 func Parse(uriString string) (*Ref, error) { 44 uri, err := url.Parse(uriString) 45 if err != nil || uri.Path == "" { 46 return nil, fmt.Errorf("invalid cref URI: %s", err) 47 } 48 49 segments := strings.Split(uri.Path, "/") 50 class, id, idx := "", "", 1 51 switch len(segments) { 52 case 3: 53 class = segments[1] 54 id = segments[2] 55 idx = 2 56 case 2: 57 id = segments[1] 58 default: 59 return nil, fmt.Errorf( 60 "invalid cref URI: path must be of format '<class>/<uuid>', but got '%s'", uri.Path) 61 } 62 if ok := strfmt.IsUUID(id); !ok { 63 return nil, fmt.Errorf("invalid cref URI: %dnd path segment must be uuid, but got '%s'", 64 idx, id) 65 } 66 67 return &Ref{ 68 Local: uri.Host == _LocalHost, 69 PeerName: uri.Host, 70 TargetID: strfmt.UUID(id), 71 Class: class, 72 }, nil 73 } 74 75 // ParseSingleRef is a safe way to generate a Ref from a models.SingleRef, a 76 // helper construct that represents the API structure. It will error if any of 77 // the input parameters are not as expected. 78 func ParseSingleRef(singleRef *models.SingleRef) (*Ref, error) { 79 return Parse(string(singleRef.Beacon)) 80 } 81 82 // New is a safe way to generate a Reference, as all required arguments must be 83 // set in the constructor fn 84 func New(peerName string, class string, target strfmt.UUID) *Ref { 85 return &Ref{ 86 Local: peerName == _LocalHost, 87 PeerName: peerName, 88 TargetID: target, 89 Class: class, 90 } 91 } 92 93 func NewLocalhost(class string, target strfmt.UUID) *Ref { 94 return New(_LocalHost, class, target) 95 } 96 97 func (r *Ref) String() string { 98 path := fmt.Sprintf("%s/%s", r.Class, r.TargetID) 99 if r.Class == "" { 100 path = fmt.Sprintf("/%s", r.TargetID) 101 } 102 uri := url.URL{ 103 Host: r.PeerName, 104 Scheme: _Schema, 105 Path: path, 106 } 107 108 return uri.String() 109 } 110 111 // SingleRef converts the parsed Ref back into the API helper construct 112 // containing a stringified representation (URI format) of the Ref 113 func (r *Ref) SingleRef() *models.SingleRef { 114 return &models.SingleRef{ 115 Beacon: strfmt.URI(r.String()), 116 } 117 }