@@ -61,7 +61,7 @@ public class JsonLDSerializer {
6161
6262 static final Logger logger = LoggerFactory .getLogger (JsonLDSerializer .class );
6363
64- static final Comparator <JsonNode > NODE_COMPARATOR = new Comparator <JsonNode >() {
64+ static final Comparator <JsonNode > NODE_COMPARATOR = new Comparator <>() {
6565
6666 @ Override
6767 public int compare (JsonNode arg0 , JsonNode arg1 ) {
@@ -176,7 +176,7 @@ public JsonLDSerializer(ObjectMapper jsonMapper, boolean pretty, boolean useExte
176176 }
177177
178178 /**
179- * @param objectToSerialize optional SPDX Document or single element to serialize
179+ * @param objectToSerialize optional SPDX Document or single element to serialize
180180 * @return the root node of the JSON serialization
181181 * @throws InvalidSPDXAnalysisException on errors retrieving the information for serialization
182182 */
@@ -197,7 +197,7 @@ public JsonNode serialize(@Nullable CoreModelObject objectToSerialize) throws In
197197 /**
198198 * Serialize SPDX document metadata and ALL elements listed in the root + all
199199 * elements listed in the elements list
200- *
200+ * <p>
201201 * All references to SPDX elements not in the root or elements lists will be
202202 * external.
203203 *
@@ -236,7 +236,8 @@ private JsonNode serializeSpdxDocument(SpdxDocument spdxDocument) throws Invalid
236236 idToSerializedId .put (anonId , documentSpdxId );
237237 logger .warn (NON_URI_WARNING , spdxDocument .getObjectUri (), documentSpdxId );
238238 }
239- graph .add (spdxDocumentToJsonNode (spdxDocument , documentSpdxId , idToSerializedId ));
239+ ObjectNode docJsonNode = spdxDocumentToJsonNode (spdxDocument , documentSpdxId , idToSerializedId );
240+ graph .add (docJsonNode );
240241 for (String type :jsonLDSchema .getElementTypes ()) {
241242 for (Element element :elementsToCopy ) {
242243 if (type .equals (element .getType ())) {
@@ -247,7 +248,9 @@ private JsonNode serializeSpdxDocument(SpdxDocument spdxDocument) throws Invalid
247248 idToSerializedId .put (anonId , serializedId );
248249 logger .warn (NON_URI_WARNING , element .getObjectUri (), serializedId );
249250 }
250- if (!(useExternalListedElements && element .getObjectUri ().startsWith (SpdxConstantsV3 .SPDX_LISTED_LICENSE_NAMESPACE ))) {
251+ if (useExternalListedElements && element .getObjectUri ().startsWith (SpdxConstantsV3 .SPDX_LISTED_LICENSE_NAMESPACE )) {
252+ addExternalLicenseReference (element .getObjectUri (), docJsonNode );
253+ } else {
251254 graph .add (modelObjectToJsonNode (element , serializedId , idToSerializedId ));
252255 }
253256 }
@@ -263,6 +266,40 @@ private JsonNode serializeSpdxDocument(SpdxDocument spdxDocument) throws Invalid
263266 }
264267 }
265268
269+ /**
270+ * Adds the listed license reference to the document external map if it is not already present
271+ * @param licenseUri listed license URI
272+ * @param docJsonNode JSON Node for the SPDX document
273+ */
274+ private void addExternalLicenseReference (String licenseUri , ObjectNode docJsonNode ) {
275+ JsonNode importsNode = docJsonNode .get ("import" );
276+ ArrayNode imports ;
277+ if (Objects .isNull (importsNode ) || !importsNode .isArray ()) {
278+ imports = jsonMapper .createArrayNode ();
279+ docJsonNode .set ("import" , imports );
280+ } else {
281+ imports = (ArrayNode )importsNode ;
282+ }
283+ boolean found = false ;
284+ for (JsonNode exMap : imports ) {
285+ if (exMap .isObject ()) {
286+ Optional <JsonNode > externalId = exMap .optional ("externalSpdxId" );
287+ if (externalId .isPresent () && externalId .get ().asText ().equals (licenseUri )) {
288+ found = true ;
289+ break ;
290+ }
291+ }
292+ }
293+ if (!found ) {
294+ ObjectNode externalMap = jsonMapper .createObjectNode ();
295+ externalMap .set ("type" , new TextNode ("ExternalMap" ));
296+ externalMap .set ("externalSpdxId" , new TextNode (licenseUri ));
297+ externalMap .set ("locationHint" , new TextNode (
298+ licenseUri .replace ("http://" , "https://" ) + ".jsonld" ));
299+ imports .add (externalMap );
300+ }
301+ }
302+
266303 /**
267304 * Serialize on the required portions of the SPDX document
268305 *
@@ -272,7 +309,7 @@ private JsonNode serializeSpdxDocument(SpdxDocument spdxDocument) throws Invalid
272309 * @return a JSON node representation of the spdxDocument
273310 * @throws InvalidSPDXAnalysisException on any SPDX related error
274311 */
275- private JsonNode spdxDocumentToJsonNode (SpdxDocument spdxDocument ,
312+ private ObjectNode spdxDocumentToJsonNode (SpdxDocument spdxDocument ,
276313 String serializedId , Map <String , String > idToSerializedId ) throws InvalidSPDXAnalysisException {
277314 ObjectNode retval = jsonMapper .createObjectNode ();
278315 retval .set (JsonLDDeserializer .SPDX_ID_PROP , new TextNode (serializedId ));
@@ -466,7 +503,7 @@ private JsonNode objectToJsonNode(Object object, IModelStore fromModelStore, Map
466503 } else if (object instanceof Integer ) {
467504 return new IntNode ((Integer ) object );
468505 } else if (object instanceof Double ) {
469- return new DoubleNode (( Double ) object );
506+ return new TextNode ( object . toString () );
470507 } else if (object instanceof IndividualUriValue ) {
471508 // it's an Enum, Individual or external element
472509 String individualUri = ((IndividualUriValue )object ).getIndividualURI ();
@@ -546,6 +583,9 @@ private JsonNode inlinedJsonNode(TypedValue tv, IModelStore fromModelStore,
546583 */
547584 private String typeToJsonType (String type ) {
548585 String [] parts = type .split ("\\ ." );
586+ if (parts .length == 1 ) {
587+ return type ;
588+ }
549589 if ("Core" .equals (parts [0 ])) {
550590 return JsonLDSchema .REVERSE_JAVA_WORDS .getOrDefault (parts [1 ], parts [1 ]);
551591 } else {
0 commit comments