package SBOM::CycloneDX::Vulnerability;

use 5.010001;
use strict;
use warnings;
use utf8;

use SBOM::CycloneDX::BomRef;
use SBOM::CycloneDX::List;
use SBOM::CycloneDX::Timestamp;

use Types::Standard qw(Str Int InstanceOf);
use Types::TypeTiny qw(ArrayLike);

use Moo;
use namespace::autoclean;

extends 'SBOM::CycloneDX::Base';

has bom_ref => (
    is     => 'rw',
    isa    => InstanceOf ['SBOM::CycloneDX::BomRef'],
    coerce => sub { ref($_[0]) ? $_[0] : SBOM::CycloneDX::BomRef->new($_[0]) }
);

has id => (is => 'rw', isa => Str);
has source => (
    is  => 'rw',
    isa => InstanceOf ['SBOM::CycloneDX::Source'] | InstanceOf ['SBOM::CycloneDX::Vulnerability::Source']
);

has references => (
    is      => 'rw',
    isa     => ArrayLike [InstanceOf ['SBOM::CycloneDX::Vulnerability::Reference']],
    default => sub { SBOM::CycloneDX::List->new }
);

has ratings => (
    is      => 'rw',
    isa     => ArrayLike [InstanceOf ['SBOM::CycloneDX::Vulnerability::Rating']],
    default => sub { SBOM::CycloneDX::List->new }
);

has cwes             => (is => 'rw', isa => ArrayLike [Int], default => sub { SBOM::CycloneDX::List->new });
has description      => (is => 'rw', isa => Str);
has detail           => (is => 'rw', isa => Str);
has recommendation   => (is => 'rw', isa => Str);
has workaround       => (is => 'rw', isa => Str);
has proof_of_concept => (is => 'rw', isa => InstanceOf ['SBOM::CycloneDX::Vulnerability::ProofOfConcept']);

has advisories => (
    is      => 'rw',
    isa     => ArrayLike [InstanceOf ['SBOM::CycloneDX::Advisory']],
    default => sub { SBOM::CycloneDX::List->new }
);

has created => (
    is     => 'rw',
    isa    => InstanceOf ['SBOM::CycloneDX::Timestamp'],
    coerce => sub { ref($_[0]) ? $_[0] : SBOM::CycloneDX::Timestamp->new($_[0]) }
);

has published => (
    is     => 'rw',
    isa    => InstanceOf ['SBOM::CycloneDX::Timestamp'],
    coerce => sub { ref($_[0]) ? $_[0] : SBOM::CycloneDX::Timestamp->new($_[0]) }
);

has updated => (
    is     => 'rw',
    isa    => InstanceOf ['SBOM::CycloneDX::Timestamp'],
    coerce => sub { ref($_[0]) ? $_[0] : SBOM::CycloneDX::Timestamp->new($_[0]) }
);

has rejected => (
    is     => 'rw',
    isa    => InstanceOf ['SBOM::CycloneDX::Timestamp'],
    coerce => sub { ref($_[0]) ? $_[0] : SBOM::CycloneDX::Timestamp->new($_[0]) }
);

has credits => (is => 'rw', isa => InstanceOf ['SBOM::CycloneDX::Vulnerability::Credits']);

has tools =>
    (is => 'rw', isa => InstanceOf ['SBOM::CycloneDX::Tools'] | ArrayLike [InstanceOf ['SBOM::CycloneDX::Tool']]);

has analysis => (is => 'rw', isa => InstanceOf ['SBOM::CycloneDX::Vulnerability::Analysis']);

has affects => (
    is      => 'rw',
    isa     => ArrayLike [InstanceOf ['SBOM::CycloneDX::Vulnerability::Affect']],
    default => sub { SBOM::CycloneDX::List->new }
);

has properties => (
    is      => 'rw',
    isa     => ArrayLike [InstanceOf ['SBOM::CycloneDX::Property']],
    default => sub { SBOM::CycloneDX::List->new }
);

sub TO_JSON {

    my $self = shift;

    my $json = {};

    $json->{'bom-ref'}      = $self->bom_ref          if $self->bom_ref;
    $json->{id}             = $self->id               if $self->id;
    $json->{source}         = $self->source           if $self->source;
    $json->{references}     = $self->references       if @{$self->references};
    $json->{ratings}        = $self->ratings          if @{$self->ratings};
    $json->{cwes}           = $self->cwes             if @{$self->cwes};
    $json->{description}    = $self->description      if $self->description;
    $json->{detail}         = $self->detail           if $self->detail;
    $json->{recommendation} = $self->recommendation   if $self->recommendation;
    $json->{workaround}     = $self->workaround       if $self->workaround;
    $json->{proofOfConcept} = $self->proof_of_concept if $self->proof_of_concept;
    $json->{advisories}     = $self->advisories       if @{$self->advisories};
    $json->{created}        = $self->created          if $self->created;
    $json->{published}      = $self->published        if $self->published;
    $json->{updated}        = $self->updated          if $self->updated;
    $json->{rejected}       = $self->rejected         if $self->rejected;
    $json->{credits}        = $self->credits          if $self->credits;
    $json->{tools}          = $self->tools            if $self->tools;
    $json->{analysis}       = $self->analysis         if $self->analysis;
    $json->{affects}        = $self->affects          if @{$self->affects};
    $json->{properties}     = $self->properties       if @{$self->properties};

    return $json;

}

1;

=encoding utf-8

=head1 NAME

SBOM::CycloneDX::Vulnerability - Vulnerability

=head1 SYNOPSIS

    SBOM::CycloneDX::Vulnerability->new();


=head1 DESCRIPTION

L<SBOM::CycloneDX::Vulnerability> Defines a weakness in a component or
service that could be exploited or triggered by a threat source.

=head2 METHODS

L<SBOM::CycloneDX::Vulnerability> inherits all methods from L<SBOM::CycloneDX::Base>
and implements the following new ones.

=over

=item SBOM::CycloneDX::Vulnerability->new( %PARAMS )

Properties:

=over

=item * C<advisories>, Published advisories of the vulnerability if provided.

=item * C<affects>, The components or services that are affected by the
vulnerability.

=item * C<analysis>, An assessment of the impact and exploitability of the
vulnerability.

=item * C<bom_ref>, An identifier which can be used to reference the
vulnerability elsewhere in the BOM. Every bom-ref must be unique within the
BOM.
Value SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid
conflicts with BOM-Links.

=item * C<created>, The date and time (timestamp) when the vulnerability
record was created in the vulnerability database.

=item * C<credits>, Individuals or organizations credited with the discovery
of the vulnerability.

=item * C<cwes>, List of Common Weaknesses Enumerations (CWEs) codes that
describes this vulnerability.

=item * C<description>, A description of the vulnerability as provided by the
source.

=item * C<detail>, If available, an in-depth description of the vulnerability
as provided by the source organization. Details often include information
useful in understanding root cause.

=item * C<id>, The identifier that uniquely identifies the vulnerability.

=item * C<proof_of_concept>, Evidence used to reproduce the vulnerability.

=item * C<properties>, Provides the ability to document properties in a
name-value store. This provides flexibility to include data not officially
supported in the standard without having to use additional namespaces or
create extensions. Unlike key-value stores, properties support duplicate
names, each potentially having different values. Property names of interest
to the general public are encouraged to be registered in the CycloneDX
Property
Taxonomy (L<https://github.com/CycloneDX/cyclonedx-property-taxonomy>). Formal
registration is optional.

=item * C<published>, The date and time (timestamp) when the vulnerability
record was first published.

=item * C<ratings>, List of vulnerability ratings

=item * C<recommendation>, Recommendations of how the vulnerability can be
remediated or mitigated.

=item * C<references>, Zero or more pointers to vulnerabilities that are the
equivalent of the vulnerability specified. Often times, the same
vulnerability may exist in multiple sources of vulnerability intelligence,
but have different identifiers. References provide a way to correlate
vulnerabilities across multiple sources of vulnerability intelligence.

=item * C<rejected>, The date and time (timestamp) when the vulnerability
record was rejected (if applicable).

=item * C<source>, The source that published the vulnerability.

=item * C<tools>, The tool(s) used to identify, confirm, or score the
vulnerability.

=item * C<updated>, The date and time (timestamp) when the vulnerability
record was last updated.

=item * C<workaround>, A bypass, usually temporary, of the vulnerability that
reduces its likelihood and/or impact. Workarounds often involve changes to
configuration or deployments.

=back

=item $vulnerability->advisories

=item $vulnerability->affects

=item $vulnerability->analysis

=item $vulnerability->bom_ref

=item $vulnerability->created

=item $vulnerability->credits

=item $vulnerability->cwes

=item $vulnerability->description

=item $vulnerability->detail

=item $vulnerability->id

=item $vulnerability->proof_of_concept

=item $vulnerability->properties

=item $vulnerability->published

=item $vulnerability->ratings

=item $vulnerability->recommendation

=item $vulnerability->references

=item $vulnerability->rejected

=item $vulnerability->source

=item $vulnerability->tools

=item $vulnerability->updated

=item $vulnerability->workaround

=back


=head1 SUPPORT

=head2 Bugs / Feature Requests

Please report any bugs or feature requests through the issue tracker
at L<https://github.com/giterlizzi/perl-SBOM-CycloneDX/issues>.
You will be notified automatically of any progress on your issue.

=head2 Source Code

This is open source software.  The code repository is available for
public review and contribution under the terms of the license.

L<https://github.com/giterlizzi/perl-SBOM-CycloneDX>

    git clone https://github.com/giterlizzi/perl-SBOM-CycloneDX.git


=head1 AUTHOR

=over 4

=item * Giuseppe Di Terlizzi <gdt@cpan.org>

=back


=head1 LICENSE AND COPYRIGHT

This software is copyright (c) 2025-2026 by Giuseppe Di Terlizzi.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
