func (i *Item) SetLanguage(s StringAttr) error {
	if !s.IsValid() {
		return cpeerr{reason: err_invalid_attribute_str}
	}
	i.language = s
	return nil
}
SetLanguage sets language of item.  returns error if s is invalid.
package cpe
import (
	"fmt"
	"strings"
)
type Item struct {
	part       PartAttr
	vendor     StringAttr
	product    StringAttr
	version    StringAttr
	update     StringAttr
	edition    StringAttr
	language   StringAttr
	sw_edition StringAttr
	target_sw  StringAttr
	target_hw  StringAttr
	other      StringAttr
}
func NewItem() *Item {
	return &Item{
		part:       PartNotSet,
		vendor:     Any,
		product:    Any,
		version:    Any,
		update:     Any,
		edition:    Any,
		language:   Any,
		sw_edition: Any,
		target_sw:  Any,
		target_hw:  Any,
		other:      Any,
	}
}
var goCpeOriginalDelim = "[goCpeOriginalDelim]"
func NewItemFromWfn(wfn string) (*Item, error) {
	if strings.HasPrefix(wfn, "wfn:[") {
		wfn = strings.TrimPrefix(wfn, "wfn:[")
	} else {
		return nil, cpeerr{reason: err_invalid_wfn}
	}
	if strings.HasSuffix(wfn, "]") {
		wfn = strings.TrimSuffix(wfn, "]")
	} else {
		return nil, cpeerr{reason: err_invalid_wfn}
	}
	item := NewItem()
	for _, attr := range strings.Split(wfn, ",") {
		sepattr := strings.Split(attr, "=")
		if len(sepattr) != 2 {
			return nil, cpeerr{reason: err_invalid_wfn}
		}
		n, v := sepattr[0], sepattr[1]
		switch n {
		case "part":
			item.part = newPartAttrFromWfnEncoded(v)
		case "vendor":
			item.vendor = newStringAttrFromWfnEncoded(v)
		case "product":
			item.product = newStringAttrFromWfnEncoded(v)
		case "version":
			item.version = newStringAttrFromWfnEncoded(v)
		case "update":
			item.update = newStringAttrFromWfnEncoded(v)
		case "edition":
			item.edition = newStringAttrFromWfnEncoded(v)
		case "language":
			item.language = newStringAttrFromWfnEncoded(v)
		case "sw_edition":
			item.sw_edition = newStringAttrFromWfnEncoded(v)
		case "target_sw":
			item.target_sw = newStringAttrFromWfnEncoded(v)
		case "target_hw":
			item.target_hw = newStringAttrFromWfnEncoded(v)
		case "other":
			item.other = newStringAttrFromWfnEncoded(v)
		}
	}
	return item, nil
}
func NewItemFromUri(uri string) (*Item, error) {
	if strings.HasPrefix(uri, "cpe:/") {
		uri = strings.TrimPrefix(uri, "cpe:/")
	} else {
		return nil, cpeerr{reason: err_invalid_wfn}
	}
	item := NewItem()
	for i, attr := range strings.Split(uri, ":") {
		switch i {
		case 0:
			item.part = newPartAttrFromUriEncoded(attr)
		case 1:
			item.vendor = newStringAttrFromUriEncoded(attr)
		case 2:
			item.product = newStringAttrFromUriEncoded(attr)
		case 3:
			item.version = newStringAttrFromUriEncoded(attr)
		case 4:
			item.update = newStringAttrFromUriEncoded(attr)
		case 5:
			editions := strings.Split(attr, "~")
			if len(editions) == 1 {
				item.edition = newStringAttrFromUriEncoded(editions[0])
			} else if len(editions) == 6 {
				item.edition = newStringAttrFromUriEncoded(editions[1])
				item.sw_edition = newStringAttrFromUriEncoded(editions[2])
				item.target_sw = newStringAttrFromUriEncoded(editions[3])
				item.target_hw = newStringAttrFromUriEncoded(editions[4])
				item.other = newStringAttrFromUriEncoded(editions[5])
			} else {
				return nil, cpeerr{reason: err_invalid_wfn}
			}
		}
	}
	return item, nil
}
func NewItemFromFormattedString(str string) (*Item, error) {
	if strings.HasPrefix(str, "cpe:2.3:") {
		str = replaceToDelim(strings.TrimPrefix(str, "cpe:2.3:"))
	} else {
		return nil, cpeerr{reason: err_invalid_wfn}
	}
	attrs := strings.Split(str, ":")
	if len(attrs) != 11 {
		return nil, cpeerr{reason: err_invalid_wfn}
	}
	item := NewItem()
	for i, attr := range attrs {
		switch i {
		case 0:
			item.part = newPartAttrFromFmtEncoded(replaceFromDelim(attr))
		case 1:
			item.vendor = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		case 2:
			item.product = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		case 3:
			item.version = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		case 4:
			item.update = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		case 5:
			item.edition = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		case 6:
			item.language = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		case 7:
			item.sw_edition = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		case 8:
			item.target_sw = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		case 9:
			item.target_hw = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		case 10:
			item.other = newStringAttrFromFmtEncoded(replaceFromDelim(attr))
		}
	}
	return item, nil
}
func (m *Item) Wfn() string {
	wfn := "wfn:["
	first := true
	for _, it := range []struct {
		name string
		attr Attribute
	}{
		{"part", m.part},
		{"vendor", m.vendor},
		{"product", m.product},
		{"version", m.version},
		{"update", m.update},
		{"edition", m.edition},
		{"language", m.language},
		{"sw_edition", m.sw_edition},
		{"target_sw", m.target_sw},
		{"target_hw", m.target_hw},
		{"other", m.other},
	} {
		if !it.attr.IsEmpty() {
			if first {
				first = false
			} else {
				wfn += ","
			}
			wfn += it.name + "=" + it.attr.wfnEncoded()
		}
	}
	wfn += "]"
	return wfn
}
func (m *Item) Uri() string {
	uri := "cpe:/"
	l := []struct {
		name string
		attr Attribute
	}{
		{"part", m.part},
		{"vendor", m.vendor},
		{"product", m.product},
		{"version", m.version},
		{"update", m.update},
	}
	for c, it := range l {
		if !it.attr.IsEmpty() {
			uri += it.attr.urlEncoded()
		}
		if c+1 != len(l) {
			uri += ":"
		}
	}
	if m.target_hw.urlEncoded() != "" ||
		m.target_sw.urlEncoded() != "" ||
		m.sw_edition.urlEncoded() != "" ||
		m.other.urlEncoded() != "" {
		uri += ":~" + m.edition.urlEncoded()
		uri += "~" + m.sw_edition.urlEncoded()
		uri += "~" + m.target_sw.urlEncoded()
		uri += "~" + m.target_hw.urlEncoded()
		uri += "~" + m.other.urlEncoded()
	} else {
		uri += ":" + m.edition.urlEncoded()
	}
	uri += ":" + m.language.urlEncoded()
	return strings.TrimRight(uri, ":*")
}
func (m *Item) Formatted() string {
	fmted := "cpe:2.3"
	for _, it := range []Attribute{
		m.part, m.vendor, m.product, m.version, m.update, m.edition, m.language, m.sw_edition, m.target_sw, m.target_hw, m.other,
	} {
		if !it.IsEmpty() {
			fmted += ":" + it.fmtString()
		} else {
			fmted += ":*"
		}
	}
	return fmted
}
func (i *Item) SetPart(p PartAttr) error {
	if !p.IsValid() {
		return cpeerr{reason: err_invalid_type, attr: []interface{}{p, "part"}}
	}
	i.part = p
	return nil
}
func (i *Item) Part() PartAttr {
	return i.part
}
func (i *Item) SetVendor(s StringAttr) error {
	if !s.IsValid() {
		return cpeerr{reason: err_invalid_attribute_str}
	}
	i.vendor = s
	return nil
}
func (i *Item) Vendor() StringAttr {
	return i.vendor
}
func (i *Item) SetProduct(s StringAttr) error {
	if !s.IsValid() {
		return cpeerr{reason: err_invalid_attribute_str}
	}
	i.product = s
	return nil
}
func (i *Item) Product() StringAttr {
	return i.product
}
func (i *Item) SetVersion(s StringAttr) error {
	if !s.IsValid() {
		return cpeerr{reason: err_invalid_attribute_str}
	}
	i.version = s
	return nil
}
func (i *Item) Version() StringAttr {
	return i.version
}
func (i *Item) SetUpdate(s StringAttr) error {
	if !s.IsValid() {
		return cpeerr{reason: err_invalid_attribute_str}
	}
	i.update = s
	return nil
}
func (i *Item) Update() StringAttr {
	return i.update
}
func (i *Item) SetEdition(s StringAttr) error {
	if !s.IsValid() {
		return cpeerr{reason: err_invalid_attribute_str}
	}
	i.edition = s
	return nil
}
func (i *Item) Edition() StringAttr {
	return i.edition
}