/*
Mender API

Combined API specification for the features of the different Mender backend services, suitable for code generation applications 

API version: 1
Contact: support@mender.io
*/

// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.

package client

import (
	"encoding/json"
	"time"
	"fmt"
)

// checks if the Software type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &Software{}

// Software Software information representing either a Release or a Manifest. Contains only the shared attributes common to both kinds.
type Software struct {
	// The name of the Software.
	Name string `json:"name"`
	// Last modification time for the Software.
	Modified *time.Time `json:"modified,omitempty"`
	// The \"types\" compatible with at least one of the Artifacts of  the Software.  If the kind of Software is 'release', these types are  \"device types\" while they are \"system types\" in the case of 'manifest' Software kind. 
	CompatibleTypes []string `json:"compatible_types,omitempty"`
	Kind string `json:"kind"`
	// Tags assigned to the Software used for filtering. Each tag must be valid a ASCII string and contain only lowercase and uppercase letters, digits, underscores, periods and hyphens.
	Tags []string `json:"tags,omitempty"`
	// Additional information describing a Software limited to 1024 characters. 
	Notes *string `json:"notes,omitempty"`
	AdditionalProperties map[string]interface{}
}

type _Software Software

// NewSoftware instantiates a new Software object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewSoftware(name string, kind string) *Software {
	this := Software{}
	this.Name = name
	this.Kind = kind
	return &this
}

// NewSoftwareWithDefaults instantiates a new Software object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewSoftwareWithDefaults() *Software {
	this := Software{}
	return &this
}

// GetName returns the Name field value
func (o *Software) GetName() string {
	if o == nil {
		var ret string
		return ret
	}

	return o.Name
}

// GetNameOk returns a tuple with the Name field value
// and a boolean to check if the value has been set.
func (o *Software) GetNameOk() (*string, bool) {
	if o == nil {
		return nil, false
	}
	return &o.Name, true
}

// SetName sets field value
func (o *Software) SetName(v string) {
	o.Name = v
}

// GetModified returns the Modified field value if set, zero value otherwise.
func (o *Software) GetModified() time.Time {
	if o == nil || IsNil(o.Modified) {
		var ret time.Time
		return ret
	}
	return *o.Modified
}

// GetModifiedOk returns a tuple with the Modified field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *Software) GetModifiedOk() (*time.Time, bool) {
	if o == nil || IsNil(o.Modified) {
		return nil, false
	}
	return o.Modified, true
}

// HasModified returns a boolean if a field has been set.
func (o *Software) HasModified() bool {
	if o != nil && !IsNil(o.Modified) {
		return true
	}

	return false
}

// SetModified gets a reference to the given time.Time and assigns it to the Modified field.
func (o *Software) SetModified(v time.Time) {
	o.Modified = &v
}

// GetCompatibleTypes returns the CompatibleTypes field value if set, zero value otherwise.
func (o *Software) GetCompatibleTypes() []string {
	if o == nil || IsNil(o.CompatibleTypes) {
		var ret []string
		return ret
	}
	return o.CompatibleTypes
}

// GetCompatibleTypesOk returns a tuple with the CompatibleTypes field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *Software) GetCompatibleTypesOk() ([]string, bool) {
	if o == nil || IsNil(o.CompatibleTypes) {
		return nil, false
	}
	return o.CompatibleTypes, true
}

// HasCompatibleTypes returns a boolean if a field has been set.
func (o *Software) HasCompatibleTypes() bool {
	if o != nil && !IsNil(o.CompatibleTypes) {
		return true
	}

	return false
}

// SetCompatibleTypes gets a reference to the given []string and assigns it to the CompatibleTypes field.
func (o *Software) SetCompatibleTypes(v []string) {
	o.CompatibleTypes = v
}

// GetKind returns the Kind field value
func (o *Software) GetKind() string {
	if o == nil {
		var ret string
		return ret
	}

	return o.Kind
}

// GetKindOk returns a tuple with the Kind field value
// and a boolean to check if the value has been set.
func (o *Software) GetKindOk() (*string, bool) {
	if o == nil {
		return nil, false
	}
	return &o.Kind, true
}

// SetKind sets field value
func (o *Software) SetKind(v string) {
	o.Kind = v
}

// GetTags returns the Tags field value if set, zero value otherwise.
func (o *Software) GetTags() []string {
	if o == nil || IsNil(o.Tags) {
		var ret []string
		return ret
	}
	return o.Tags
}

// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *Software) GetTagsOk() ([]string, bool) {
	if o == nil || IsNil(o.Tags) {
		return nil, false
	}
	return o.Tags, true
}

// HasTags returns a boolean if a field has been set.
func (o *Software) HasTags() bool {
	if o != nil && !IsNil(o.Tags) {
		return true
	}

	return false
}

// SetTags gets a reference to the given []string and assigns it to the Tags field.
func (o *Software) SetTags(v []string) {
	o.Tags = v
}

// GetNotes returns the Notes field value if set, zero value otherwise.
func (o *Software) GetNotes() string {
	if o == nil || IsNil(o.Notes) {
		var ret string
		return ret
	}
	return *o.Notes
}

// GetNotesOk returns a tuple with the Notes field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *Software) GetNotesOk() (*string, bool) {
	if o == nil || IsNil(o.Notes) {
		return nil, false
	}
	return o.Notes, true
}

// HasNotes returns a boolean if a field has been set.
func (o *Software) HasNotes() bool {
	if o != nil && !IsNil(o.Notes) {
		return true
	}

	return false
}

// SetNotes gets a reference to the given string and assigns it to the Notes field.
func (o *Software) SetNotes(v string) {
	o.Notes = &v
}

func (o Software) MarshalJSON() ([]byte, error) {
	toSerialize,err := o.ToMap()
	if err != nil {
		return []byte{}, err
	}
	return json.Marshal(toSerialize)
}

func (o Software) ToMap() (map[string]interface{}, error) {
	toSerialize := map[string]interface{}{}
	toSerialize["name"] = o.Name
	if !IsNil(o.Modified) {
		toSerialize["modified"] = o.Modified
	}
	if !IsNil(o.CompatibleTypes) {
		toSerialize["compatible_types"] = o.CompatibleTypes
	}
	toSerialize["kind"] = o.Kind
	if !IsNil(o.Tags) {
		toSerialize["tags"] = o.Tags
	}
	if !IsNil(o.Notes) {
		toSerialize["notes"] = o.Notes
	}

	for key, value := range o.AdditionalProperties {
		toSerialize[key] = value
	}

	return toSerialize, nil
}

func (o *Software) UnmarshalJSON(data []byte) (err error) {
	// This validates that all required properties are included in the JSON object
	// by unmarshalling the object into a generic map with string keys and checking
	// that every required field exists as a key in the generic map.
	requiredProperties := []string{
		"name",
		"kind",
	}

	allProperties := make(map[string]interface{})

	err = json.Unmarshal(data, &allProperties)

	if err != nil {
		return err;
	}

	for _, requiredProperty := range(requiredProperties) {
		if _, exists := allProperties[requiredProperty]; !exists {
			return fmt.Errorf("no value given for required property %v", requiredProperty)
		}
	}

	varSoftware := _Software{}

	err = json.Unmarshal(data, &varSoftware)

	if err != nil {
		return err
	}

	*o = Software(varSoftware)

	additionalProperties := make(map[string]interface{})

	if err = json.Unmarshal(data, &additionalProperties); err == nil {
		delete(additionalProperties, "name")
		delete(additionalProperties, "modified")
		delete(additionalProperties, "compatible_types")
		delete(additionalProperties, "kind")
		delete(additionalProperties, "tags")
		delete(additionalProperties, "notes")
		o.AdditionalProperties = additionalProperties
	}

	return err
}

type NullableSoftware struct {
	value *Software
	isSet bool
}

func (v NullableSoftware) Get() *Software {
	return v.value
}

func (v *NullableSoftware) Set(val *Software) {
	v.value = val
	v.isSet = true
}

func (v NullableSoftware) IsSet() bool {
	return v.isSet
}

func (v *NullableSoftware) Unset() {
	v.value = nil
	v.isSet = false
}

func NewNullableSoftware(val *Software) *NullableSoftware {
	return &NullableSoftware{value: val, isSet: true}
}

func (v NullableSoftware) MarshalJSON() ([]byte, error) {
	return json.Marshal(v.value)
}

func (v *NullableSoftware) UnmarshalJSON(src []byte) error {
	v.isSet = true
	return json.Unmarshal(src, &v.value)
}


