Skip to content

Commit 1d1bee6

Browse files
committed
Fix getting started documentation
Fixes #294 Also adds an example and unit test to help check example code
1 parent 3373f9a commit 1d1bee6

File tree

3 files changed

+137
-18
lines changed

3 files changed

+137
-18
lines changed

GETTING-STARTED.md

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ The `SpdxModelFactory.init()` will not overwrite an already initialized default
6363

6464
### Programmatically Creating SPDX Data
6565

66+
See the [Spdx3Example.java](src/examples/java/org/spdx/example/Spdx3Example.java) file for the complete code example.
67+
6668
All SPDX elements are required to have a unique SPDX ID which is an Object URI. In the SPDX Java libraries, this is commonly referred to as the `objectUri` to avoid confusion with the SPDX 2.X version short SPDX IDs.
6769

6870
A good practice is to create a common prefix to use for your programmatic session. The prefix should be unique to the session. There are convenience methods in the library to append identifiers unique to the model store.
@@ -73,42 +75,44 @@ In these examples, we'll use:
7375
String prefix = "https://org.spdx.spdxdata/899b1918-f72a-4755-9215-6262b3c346df/";
7476
```
7577

76-
Since SPDX 3.0 requires creation info on every element, the easiest way to start is to use the SPDX 3 model convenience method `SpdxModelClassFactory.createCreationInfo(...)` which will create the `Agent` and `CreationInfo` classes which can be added to all the subsequent elements.
78+
Since SPDX 3.0 requires creation info on every element, the easiest way to start is to use the SPDX 3 model convenience method `SpdxModelFactory.createCreationInfoV3(...)` which will create the `Agent` and `CreationInfo` classes which can be added to all the subsequent elements.
7779

7880
For example:
7981

8082
```java
81-
CreationInfo creationInfo = SpdxModelClassFactory.createCreationInfo(
83+
CreationInfo creationInfo = SpdxModelFactoryV3.createCreationInfo(
8284
modelStore, prefix + "Agent/Gary01123", "Gary O'Neall",
8385
copyManager);
8486
```
8587

8688
We're now ready to create our first SPDX element. You can start anywhere, but let's start with an SBOM element.
8789

88-
There is a factory method you can use to get started:
90+
Every SPDX object has builder methods for all the SPDX objects.
8991

90-
```java
91-
Sbom sbom = SpdxModelClassFactory.getModelObject(modelStore,
92-
prefix + "sbom/mysbom", SpdxConstantsV3.SOFTWARE_SBOM,
93-
copyManager, true, prefix);
94-
```
95-
96-
Let's not forget to add the creation info:
92+
To build the initial SBOM, we can call the builder method for Sbom.
93+
The only parameter is the Object URI for the element - we'll use the same prefix for consistency.
94+
We might as well add a name while we're at it.
9795

9896
```java
99-
sbom.setCreationInfo(creationInfo);
97+
Sbom sbom = creationInfo.createSbom(prefix + "sbom/mysbom")
98+
.setName("My SBOM")
99+
.build();
100100
```
101101

102-
From here on, things get easier. We can get and set properties to the sbom we just created.
102+
Note that the builder add all the creation information from the
103+
object calling the builder method, so no need to add the creationInfo,
104+
modelStore or copyManager.
105+
106+
From here on out, we can just use the builder methods to create objects and the getter / setter methods.
103107

104-
If we want to create another SPDX object or element, we can use the builder convenience methods available to all SPDX objects. For example, if we want to create a package to add to the SBOM we can call:
108+
For example, if we want to create a package to add to the SBOM as a root we can call:
105109

106110
```java
107-
sbom.getElements().add(
108-
sbom.createSpdxPackage(prefix + "package/mypackage")
109-
.setName("Package Name")
110-
.build()
111-
);
111+
SpdxPackage pkg = sbom.createSpdxPackage(prefix + "package/mypackage")
112+
.setName("Package Name")
113+
.build();
114+
sbom.getElements().add(pkg);
115+
sbom.getRootElements().add(pkg);
112116
```
113117

114118
The model store, creation info, copy manager, and prefix information will all be copied from the sbom allowing you to focus just on the properties you need to add.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2025 Source Auditor Inc.
3+
* SPDX-FileType: SOURCE
4+
* SPDX-License-Identifier: Apache-2.0
5+
* <p>
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
* <p>
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
* <p>
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.spdx.example;
20+
21+
import org.spdx.core.IModelCopyManager;
22+
import org.spdx.core.InvalidSPDXAnalysisException;
23+
import org.spdx.library.ModelCopyManager;
24+
import org.spdx.library.SpdxModelFactory;
25+
import org.spdx.library.model.v3_0_1.SpdxModelClassFactoryV3;
26+
import org.spdx.library.model.v3_0_1.core.CreationInfo;
27+
import org.spdx.library.model.v3_0_1.software.Sbom;
28+
import org.spdx.library.model.v3_0_1.software.SpdxPackage;
29+
import org.spdx.storage.simple.InMemSpdxStore;
30+
31+
/**
32+
* Example which creates an SBOM from scratch
33+
* NOTE: Snippets from this file are used in the GETTING_STARTED.md file - any changes to this file
34+
* should update the GETTING_STARTED.md file
35+
*/
36+
public class Spdx3Example {
37+
38+
public static Sbom createSbomFromScratch() throws InvalidSPDXAnalysisException {
39+
// Before executing any of the model class methods, the model versions need to be initialized
40+
SpdxModelFactory.init();
41+
// SPDX data is stored in a "model store" and copying between model stores requires a copy manager.
42+
// A simple store is provided in the java library
43+
InMemSpdxStore modelStore = new InMemSpdxStore();
44+
IModelCopyManager copyManager = new ModelCopyManager();
45+
46+
// All SPDX elements are required to have a unique SPDX ID which is an Object URI.
47+
// In the SPDX Java libraries, this is commonly referred to as the objectUri to avoid confusion with the SPDX 2.X version short SPDX IDs.
48+
// A good practice is to create a common prefix to use for your programmatic session.
49+
// The prefix should be unique to the session.
50+
// There are convenience methods in the library to append identifiers unique to the model store.
51+
String prefix = "https://org.spdx.spdxdata/899b1918-f72a-4755-9215-6262b3c346df/";
52+
53+
// Since SPDX 3.0 requires creation info on every element,
54+
// the easiest way to start is to use the SPDX 3 model convenience method SpdxModelClassFactoryV3.createCreationInfo(...)
55+
// which will create the Agent and CreationInfo classes which can be added to all the subsequent elements.
56+
CreationInfo creationInfo = SpdxModelClassFactoryV3.createCreationInfo(
57+
modelStore, prefix + "Agent/Gary01123", "Gary O'Neall",
58+
copyManager);
59+
60+
// Every SPDX object has builder methods for all the SPDX objects.
61+
// To build the initial SBOM, we can call the builder method for Sbom.
62+
// The only parameter is the Object URI for the element - we'll use the same prefix for consistency.
63+
Sbom sbom = creationInfo.createSbom(prefix + "sbom/mysbom")
64+
// we might as well add a name while we're at it. - you can add any of the property during the build
65+
// Don't worry if you don't have all the properties, they can be added later
66+
.setName("My SBOM")
67+
.build();
68+
69+
// From here on out, we can just use the builder methods to create objects and the getter / setter methods
70+
// on the objects to update any properties.
71+
// Let's create an SPDX Package and add it to the SBOM and make it the root
72+
SpdxPackage pkg = sbom.createSpdxPackage(prefix + "package/mypackage")
73+
.setName("Package Name")
74+
.build();
75+
sbom.getElements().add(pkg);
76+
sbom.getRootElements().add(pkg);
77+
78+
return sbom;
79+
}
80+
81+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2025 Source Auditor Inc.
3+
* SPDX-FileType: SOURCE
4+
* SPDX-License-Identifier: Apache-2.0
5+
* <p>
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
* <p>
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
* <p>
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.spdx.example;
20+
21+
import junit.framework.TestCase;
22+
import org.spdx.core.InvalidSPDXAnalysisException;
23+
import org.spdx.library.model.v3_0_1.software.Sbom;
24+
25+
import java.util.List;
26+
27+
public class Spdx3ExampleTest extends TestCase {
28+
29+
public void testCreateSbomFromScratch() throws InvalidSPDXAnalysisException {
30+
Sbom result = Spdx3Example.createSbomFromScratch();
31+
List<String> verify = result.verify();
32+
assertTrue(verify.isEmpty());
33+
}
34+
}

0 commit comments

Comments
 (0)