111 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package atom
 | |
| 
 | |
| import (
 | |
| 	"encoding/xml"
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| type Link struct {
 | |
| 	XMLName xml.Name `xml:"link"`
 | |
| 	*CommonAttributes
 | |
| 	Title    string `xml:"title,attr,omitempty"`
 | |
| 	Href     string `xml:"href,attr"` // IRI
 | |
| 	Rel      string `xml:"rel,attr,omitempty"`
 | |
| 	Type     string `xml:"type,attr,omitempty"`     // MediaType
 | |
| 	HrefLang string `xml:"hreflang,attr,omitempty"` // LanguageTag
 | |
| 	Length   uint   `xml:"length,attr,omitempty"`
 | |
| }
 | |
| 
 | |
| // NewLink creates a new Link. It returns a *Link and an error.
 | |
| func NewLink(href string) (*Link, error) {
 | |
| 	if !isValidIRI(href) {
 | |
| 		return nil, fmt.Errorf("href %v not correctly formatted", href)
 | |
| 	}
 | |
| 
 | |
| 	return &Link{Href: href}, nil
 | |
| }
 | |
| 
 | |
| // SetType sets the Type attribute of the Link. It returns an error.
 | |
| func (l *Link) SetType(t string) error {
 | |
| 	if !isValidMediaType(t) {
 | |
| 		return fmt.Errorf("type %v invalid media type", t)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // SetHrefLang sets the HrefLang attribute of the Link. It returns an error.
 | |
| func (l *Link) SetHrefLang(h string) error {
 | |
| 	if !isValidLanguageTag(h) {
 | |
| 		return fmt.Errorf("hreflang %v invalid language tag", h)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Check checks the Link for incompatibilities with RFC4287. It returns an
 | |
| // error.
 | |
| func (l *Link) Check() error {
 | |
| 	if l.Href == "" {
 | |
| 		return fmt.Errorf("href attribute of link %v empty", l)
 | |
| 	} else {
 | |
| 		if !isValidIRI(l.Href) {
 | |
| 			return fmt.Errorf("href attribute of link %v not correctly formatted", l)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if l.Rel != "" {
 | |
| 		if strings.Contains(l.Rel, ":") && !isValidIRI(l.Rel) {
 | |
| 			return fmt.Errorf("rel attribute of link %v not correctly formatted", l)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if l.Type != "" {
 | |
| 		if !isValidMediaType(l.Type) {
 | |
| 			return fmt.Errorf("type attribute of link %v invalid media type", l)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if l.HrefLang != "" {
 | |
| 		if !isValidLanguageTag(l.HrefLang) {
 | |
| 			return fmt.Errorf("hreflang attribute of link %v invalid language tag", l)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // hasAlternateDuplicateLinks checks whether multiple Links with Rel
 | |
| // "alternate" also have Type and HrefLang in common. It returns a bool.
 | |
| // atom:feed/entry elements MUST NOT contain more than one atom:link element
 | |
| // with a rel attribute value of "alternate" that has the same combination of
 | |
| // type and hreflang attribute values.
 | |
| func hasAlternateDuplicateLinks(l []*Link) bool {
 | |
| 	linkMap := make(map[string]bool)
 | |
| 
 | |
| 	for _, link := range l {
 | |
| 		if link.Rel == "alternate" {
 | |
| 			key := fmt.Sprint(link.Type, "|", link.HrefLang)
 | |
| 			if linkMap[key] {
 | |
| 				return true
 | |
| 			}
 | |
| 			linkMap[key] = true
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // alternateRelExists checks whether multiple Links with Rel "alternate" exist.
 | |
| // It returns a bool.
 | |
| func alternateRelExists(l []*Link) bool {
 | |
| 	for _, link := range l {
 | |
| 		if link.Rel == "alternate" {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return false
 | |
| }
 |