func (m *ProvidersMatch) AddVersionEnd(version string, excluding bool) {
	if excluding {
		m.VersionEndExcluding = version
	} else {
		m.VersionEndIncluding = version
	}
}
AddVersionEnd adds the ending version to a Match, along with
whether that version is included or excluded from the Match.
package schema
import (
	"errors"
	"fmt"
	"time"
	nvd "github.com/facebookincubator/nvdtools/cvefeed/nvd/schema"
)
const (
	providersDataFormat  = "MITRE"
	providersDataType    = "CVE"
	providersDataLang    = "en"
	providersDataVersion = "4.0"
	providersTimeLayout  = "2006-01-02T15:04Z"
)
type ProvidersItem struct {
	Vendor           string
	ID               string
	Description      string
	CWEs             []string
	References       *ProvidersReferences
	Configuration    *ProvidersConfiguration
	CVSS2            *ProvidersCVSS
	CVSS3            *ProvidersCVSS
	LastModifiedDate *time.Time
	PublishedDate    *time.Time
}
type ProvidersCVSS struct {
	BaseScore     float64
	TemporalScore float64
	Vector        string
}
type ProvidersReferences struct {
	referenceData []*nvd.CVEJSON40Reference
}
type ProvidersConfiguration struct {
	Nodes []*ProvidersNode
}
type ProvidersNode struct {
	matches            []*nvd.NVDCVEFeedJSON10DefCPEMatch
	conditionalMatches []*nvd.NVDCVEFeedJSON10DefCPEMatch
}
type ProvidersMatch struct {
	CPE22URI              string
	CPE23URI              string
	VersionStartExcluding string
	VersionStartIncluding string
	VersionEndExcluding   string
	VersionEndIncluding   string
	Vulnerable            bool
}
func ProvidersConvertStrTime(layout, strTime string) (*time.Time, error) {
	if strTime == "" {
		return nil, nil
	}
	t, err := time.Parse(layout, strTime)
	if err != nil {
		return nil, err
	}
	return &t, nil
}
func providersConvertTime(t *time.Time) string {
	if t == nil {
		return ""
	}
	return t.Format(providersTimeLayout)
}
func ProvidersNewItem(item *ProvidersItem) (*nvd.NVDCVEFeedJSON10DefCVEItem, error) {
	if err := item.validate(); err != nil {
		return nil, fmt.Errorf("validation error: %v", err)
	}
	return &nvd.NVDCVEFeedJSON10DefCVEItem{
		CVE: &nvd.CVEJSON40{
			CVEDataMeta: &nvd.CVEJSON40CVEDataMeta{
				ID:       item.ID,
				ASSIGNER: item.Vendor,
			},
			DataFormat:  providersDataFormat,
			DataType:    providersDataType,
			DataVersion: providersDataVersion,
			Description: &nvd.CVEJSON40Description{
				DescriptionData: []*nvd.CVEJSON40LangString{
					{
						Lang:  providersDataLang,
						Value: item.Description,
					},
				},
			},
			Problemtype: item.problemType(),
			References:  item.references(),
		},
		Configurations: item.Configuration.convertToNVD(),
		Impact: &nvd.NVDCVEFeedJSON10DefImpact{
			BaseMetricV2: &nvd.NVDCVEFeedJSON10DefImpactBaseMetricV2{
				CVSSV2: item.cvssV20(),
			},
			BaseMetricV3: &nvd.NVDCVEFeedJSON10DefImpactBaseMetricV3{
				CVSSV3: item.cvssV30(),
			},
		},
		LastModifiedDate: providersConvertTime(item.LastModifiedDate),
		PublishedDate:    providersConvertTime(item.PublishedDate),
	}, nil
}
func (item *ProvidersItem) validate() error {
	if item.ID == "" || item.Vendor == "" || item.Description == "" {
		return errors.New("id, vendor and description can't be empty")
	}
	if item.Configuration == nil {
		return errors.New("Configuration can't be nil")
	}
	return nil
}
func (item *ProvidersItem) cvssV20() *nvd.CVSSV20 {
	if item.CVSS2 == nil {
		return nil
	}
	return &nvd.CVSSV20{
		BaseScore:     item.CVSS2.BaseScore,
		TemporalScore: item.CVSS2.TemporalScore,
		VectorString:  item.CVSS2.Vector,
	}
}
func (item *ProvidersItem) cvssV30() *nvd.CVSSV30 {
	if item.CVSS3 == nil {
		return nil
	}
	return &nvd.CVSSV30{
		BaseScore:     item.CVSS3.BaseScore,
		TemporalScore: item.CVSS3.TemporalScore,
		VectorString:  item.CVSS3.Vector,
	}
}
func (item *ProvidersItem) references() *nvd.CVEJSON40References {
	if item.References == nil || item.References.referenceData == nil {
		return nil
	}
	return &nvd.CVEJSON40References{
		ReferenceData: item.References.referenceData,
	}
}
func (item *ProvidersItem) problemType() *nvd.CVEJSON40Problemtype {
	if item.CWEs == nil {
		return nil
	}
	var weaknesses []*nvd.CVEJSON40LangString
	for _, cwe := range item.CWEs {
		weaknesses = append(weaknesses, &nvd.CVEJSON40LangString{
			Lang:  providersDataLang,
			Value: cwe,
		})
	}
	return &nvd.CVEJSON40Problemtype{
		ProblemtypeData: []*nvd.CVEJSON40ProblemtypeProblemtypeData{
			{
				Description: weaknesses,
			},
		},
	}
}
func ProvidersNewReferences() *ProvidersReferences {
	return &ProvidersReferences{}
}
func (r *ProvidersReferences) Add(name, url string) {
	r.referenceData = append(r.referenceData, &nvd.CVEJSON40Reference{
		Name: name,
		URL:  url,
	})
}
func ProvidersNewConfiguration() *ProvidersConfiguration {
	return &ProvidersConfiguration{
		Nodes: []*ProvidersNode{},
	}
}
func (c *ProvidersConfiguration) convertToNVD() *nvd.NVDCVEFeedJSON10DefConfigurations {
	var nvdNodes []*nvd.NVDCVEFeedJSON10DefNode
	for _, node := range c.Nodes {
		nvdNode := &nvd.NVDCVEFeedJSON10DefNode{}
		if len(node.conditionalMatches) > 0 {
			nvdNode.Operator = "AND"
			nvdNode.Children = []*nvd.NVDCVEFeedJSON10DefNode{
				&nvd.NVDCVEFeedJSON10DefNode{
					Operator: "OR",
					CPEMatch: node.matches,
				},
				&nvd.NVDCVEFeedJSON10DefNode{
					Operator: "OR",
					CPEMatch: node.conditionalMatches,
				},
			}
		} else {
			nvdNode.Operator = "OR"
			nvdNode.CPEMatch = node.matches
		}
		nvdNodes = append(nvdNodes, nvdNode)
	}
	return &nvd.NVDCVEFeedJSON10DefConfigurations{
		CVEDataVersion: providersDataVersion,
		Nodes:          nvdNodes,
	}
}
func (c *ProvidersConfiguration) NewNode() *ProvidersNode {
	node := &ProvidersNode{
		matches:            []*nvd.NVDCVEFeedJSON10DefCPEMatch{},
		conditionalMatches: []*nvd.NVDCVEFeedJSON10DefCPEMatch{},
	}
	c.Nodes = append(c.Nodes, node)
	return node
}
func (node *ProvidersNode) AddMatch(m *ProvidersMatch) {
	node.matches = append(node.matches, m.convertToNVD())
}
func (node *ProvidersNode) AddConditionalMatch(m *ProvidersMatch) {
	node.conditionalMatches = append(node.conditionalMatches, m.convertToNVD())
}
func ProvidersNewMatch(cpe22uri, cpe23uri string, vulnerable bool) *ProvidersMatch {
	return &ProvidersMatch{
		CPE22URI:   cpe22uri,
		CPE23URI:   cpe23uri,
		Vulnerable: vulnerable,
	}
}
func (m *ProvidersMatch) convertToNVD() *nvd.NVDCVEFeedJSON10DefCPEMatch {
	return &nvd.NVDCVEFeedJSON10DefCPEMatch{
		Cpe22Uri:              m.CPE22URI,
		Cpe23Uri:              m.CPE23URI,
		VersionStartExcluding: m.VersionStartExcluding,
		VersionStartIncluding: m.VersionStartIncluding,
		VersionEndExcluding:   m.VersionEndExcluding,
		VersionEndIncluding:   m.VersionEndIncluding,
		Vulnerable:            m.Vulnerable,
	}
}
func (m *ProvidersMatch) AddVersionStart(version string, excluding bool) {
	if excluding {
		m.VersionStartExcluding = version
	} else {
		m.VersionStartIncluding = version
	}
}