Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#348 implement deep copy rather than serialization #352

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/CycloneDX.Core/BomUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,7 @@ internal static Bom CopyBomAndDowngrade(Bom bom)

public static Bom Copy(this Bom bom)
{
var protoBom = Protobuf.Serializer.SerializeForDeepCopy(bom);
var bomCopy = Protobuf.Serializer.Deserialize(protoBom);
return bomCopy;
return (Bom)bom.Clone();
}

public static void EnqueueMany<T>(this Queue<T> queue, IEnumerable<T> items)
Expand Down
31 changes: 27 additions & 4 deletions src/CycloneDX.Core/Models/Annotation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,26 @@
using System.Xml.Serialization;
using System.Text.Json.Serialization;
using ProtoBuf;
using System.Linq;

namespace CycloneDX.Models
{
[ProtoContract]
public class Annotation
public class Annotation : ICloneable
{
[XmlType("subject")]
public class XmlAnnotationSubject
public class XmlAnnotationSubject : ICloneable
{
[XmlAttribute("ref")]
public string Ref { get; set; }

public object Clone()
{
return new XmlAnnotationSubject()
{
Ref = this.Ref
};
}
}

[XmlAttribute("bom-ref")]
Expand Down Expand Up @@ -80,10 +89,24 @@ public DateTime? Timestamp
get => _timestamp;
set { _timestamp = BomUtils.UtcifyDateTime(value); }
}
public bool ShouldSerializeTimestamp() { return Timestamp != null; }


[XmlElement("text")]
[ProtoMember(5)]
public string Text { get; set; }

public bool ShouldSerializeTimestamp() { return Timestamp != null; }

public object Clone()
{
return new Annotation()
{
Annotator = (AnnotatorChoice)this.Annotator.Clone(),
BomRef = this.BomRef,
Subjects = this.Subjects.Select(x => x).ToList(),
Text = this.Text,
Timestamp = this.Timestamp,
XmlSubjects = this.XmlSubjects.Select(x => (XmlAnnotationSubject)x.Clone()).ToList()
};
}
}
}
14 changes: 13 additions & 1 deletion src/CycloneDX.Core/Models/AnnotatorChoice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) OWASP Foundation. All Rights Reserved.

using System;
using System.Xml.Serialization;
using ProtoBuf;

namespace CycloneDX.Models
{
[ProtoContract]
public class AnnotatorChoice
public class AnnotatorChoice : ICloneable
{
[XmlElement("organization")]
[ProtoMember(1)]
Expand All @@ -38,5 +39,16 @@ public class AnnotatorChoice
[XmlElement("service")]
[ProtoMember(4)]
public Service Service { get; set; }

public object Clone()
{
return new AnnotatorChoice()
{
Component = (Component)this.Component.Clone(),
Individual = (OrganizationalContact)this.Individual.Clone(),
Organization = (OrganizationalEntity)this.Organization.Clone(),
Service = (Service)this.Service.Clone(),
};
}
}
}
13 changes: 12 additions & 1 deletion src/CycloneDX.Core/Models/AttachedText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) OWASP Foundation. All Rights Reserved.

using System;
using System.Xml.Serialization;
using ProtoBuf;

namespace CycloneDX.Models
{
[ProtoContract]
public class AttachedText
public class AttachedText : ICloneable
{
[XmlAttribute("content-type")]
[ProtoMember(1)]
Expand All @@ -34,5 +35,15 @@ public class AttachedText
[XmlText]
[ProtoMember(3)]
public string Content { get; set; }

public object Clone()
{
return new AttachedText()
{
Content = Content,
ContentType = ContentType,
Encoding = Encoding
};
}
}
}
48 changes: 36 additions & 12 deletions src/CycloneDX.Core/Models/Bom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using System.Linq;
using System.Text.Json.Serialization;
using System.Xml.Serialization;
using CycloneDX.Models.Vulnerabilities;
using ProtoBuf;

namespace CycloneDX.Models
Expand All @@ -29,7 +30,7 @@ namespace CycloneDX.Models
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
[XmlRoot("bom", IsNullable=false)]
[ProtoContract]
public class Bom
public class Bom : ICloneable
{
[XmlIgnore]
public string BomFormat => "CycloneDX";
Expand Down Expand Up @@ -111,8 +112,7 @@ public int NonNullableVersion
Version = value;
}
}
public bool ShouldSerializeNonNullableVersion() { return Version.HasValue; }


[XmlElement("metadata")]
[ProtoMember(4)]
public Metadata Metadata { get; set; }
Expand All @@ -126,20 +126,17 @@ public int NonNullableVersion
[XmlArrayItem("service")]
[ProtoMember(6)]
public List<Service> Services { get; set; }
public bool ShouldSerializeServices() { return Services?.Count > 0; }


[XmlArray("externalReferences")]
[XmlArrayItem("reference")]
[ProtoMember(7)]
public List<ExternalReference> ExternalReferences { get; set; }
public bool ShouldSerializeExternalReferences() { return ExternalReferences?.Count > 0; }


[XmlArray("dependencies")]
[XmlArrayItem("dependency")]
[ProtoMember(8)]
public List<Dependency> Dependencies { get; set; }
public bool ShouldSerializeDependencies() { return Dependencies?.Count > 0; }


[XmlArray("compositions")]
[XmlArrayItem("composition")]
[ProtoMember(9)]
Expand All @@ -149,24 +146,51 @@ public int NonNullableVersion
[XmlArrayItem("vulnerability")]
[ProtoMember(10)]
public List<Vulnerabilities.Vulnerability> Vulnerabilities { get; set; }
public bool ShouldSerializeVulnerabilities() { return Vulnerabilities?.Count > 0; }

[XmlArray("annotations")]
[XmlArrayItem("annotation")]
[ProtoMember(11)]
public List<Annotation> Annotations { get; set; }
public bool ShouldSerializeAnnotations() { return Annotations?.Count > 0; }

[XmlArray("properties")]
[XmlArrayItem("property")]
[ProtoMember(12)]
public List<Property> Properties { get; set; }
public bool ShouldSerializeProperties() { return Properties?.Count > 0; }

[XmlArray("formulation")]
[XmlArrayItem("formula")]
[ProtoMember(13)]
public List<Formula> Formulation { get; set; }

public bool ShouldSerializeNonNullableVersion() { return Version.HasValue; }
public bool ShouldSerializeServices() { return Services?.Count > 0; }
public bool ShouldSerializeExternalReferences() { return ExternalReferences?.Count > 0; }
public bool ShouldSerializeDependencies() { return Dependencies?.Count > 0; }
public bool ShouldSerializeVulnerabilities() { return Vulnerabilities?.Count > 0; }
public bool ShouldSerializeAnnotations() { return Annotations?.Count > 0; }
public bool ShouldSerializeProperties() { return Properties?.Count > 0; }
public bool ShouldSerializeFormulation() { return Formulation?.Count > 0; }

public object Clone()
{
return new Bom()
{
Annotations = this.Annotations.Select(x => (Annotation)x.Clone()).ToList(),
Components = this.Components.Select(x => (Component)x.Clone()).ToList(),
Compositions = this.Compositions.Select(x => (Composition)x.Clone()).ToList(),
Dependencies = this.Dependencies.Select(x => (Dependency)x.Clone()).ToList(),
ExternalReferences = this.ExternalReferences.Select(x => (ExternalReference)x.Clone()).ToList(),
Formulation = this.Formulation.Select(x => (Formula)x.Clone()).ToList(),
Metadata = (Metadata)this.Metadata.Clone(),
NonNullableVersion = this.NonNullableVersion,
Properties = this.Properties.Select(x => (Property)x.Clone()).ToList(),
SerialNumber = this.SerialNumber,
Services = this.Services.Select(x => (Service)x.Clone()).ToList(),
SpecVersion = this.SpecVersion,
SpecVersionString = this.SpecVersionString,
Version = this.Version,
Vulnerabilities = this.Vulnerabilities.Select(x => (Vulnerability)x.Clone()).ToList(),
};
}
}
}
30 changes: 27 additions & 3 deletions src/CycloneDX.Core/Models/Callstack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Text.Json.Serialization;
using System.Xml;
Expand All @@ -28,11 +29,11 @@ namespace CycloneDX.Models
{
[XmlType("callstack")]
[ProtoContract]
public class Callstack
public class Callstack : ICloneable
{
[XmlType("frame")]
[ProtoContract]
public class Frame
public class Frame : ICloneable
{
[XmlElement("package")]
[ProtoMember(1)]
Expand All @@ -50,7 +51,6 @@ public class Frame
[XmlArrayItem("parameter")]
[ProtoMember(4)]
public List<string> Parameters { get; set; }
public bool ShouldSerializeParameters() { return Parameters?.Count > 0; }

[XmlElement("line")]
[ProtoMember(5)]
Expand All @@ -63,11 +63,35 @@ public class Frame
[XmlElement("fullFilename")]
[ProtoMember(7)]
public string FullFilename { get; set; }

public bool ShouldSerializeParameters() { return Parameters?.Count > 0; }

public object Clone()
{
return new Frame()
{
Column = this.Column,
FullFilename = this.FullFilename,
Function = this.Function,
Line = this.Line,
Module = this.Module,
Package = this.Package,
Parameters = this.Parameters.Select(x => x).ToList()
};
}
}

[XmlArray("frames")]
[XmlArrayItem("frame")]
[ProtoMember(1)]
public List<Frame> Frames { get; set; }

public object Clone()
{
return new Callstack()
{
Frames = this.Frames.Select(x => (Frame)x.Clone()).ToList()
};
}
}
}
13 changes: 12 additions & 1 deletion src/CycloneDX.Core/Models/Command.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text.Json.Serialization;
using System.Xml.Serialization;
using ProtoBuf;
Expand All @@ -26,7 +27,7 @@ namespace CycloneDX.Models
{
[XmlType("command")]
[ProtoContract]
public class Command
public class Command : ICloneable
{
[XmlElement("executed")]
[ProtoMember(1)]
Expand All @@ -36,6 +37,16 @@ public class Command
[XmlArrayItem("property")]
[ProtoMember(2)]
public List<Property> Properties { get; set; }

public bool ShouldSerializeProperties() { return Properties?.Count > 0; }

public object Clone()
{
return new Command()
{
Executed = this.Executed,
Properties = this.Properties.Select(x => (Property)x.Clone()).ToList()
};
}
}
}
15 changes: 14 additions & 1 deletion src/CycloneDX.Core/Models/Commit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) OWASP Foundation. All Rights Reserved.

using System;
using System.Xml.Serialization;
using ProtoBuf;

namespace CycloneDX.Models
{
[ProtoContract]
public class Commit
public class Commit : ICloneable
{
[XmlElement("uid")]
[ProtoMember(1)]
Expand All @@ -42,5 +43,17 @@ public class Commit
[XmlElement("message")]
[ProtoMember(5)]
public string Message { get; set; }

public object Clone()
{
return new Commit()
{
Author = (IdentifiableAction)this.Author.Clone(),
Committer = (IdentifiableAction)this.Committer.Clone(),
Message = this.Message,
Uid = this.Uid,
Url = this.Url,
};
}
}
}
Loading
Loading