@@ -244,7 +244,7 @@ private void copyCollectionProperty(IModelStore toStore, String toObjectUri, IMo
244244 * @param sourceUri URI for the Source object
245245 * @param type Type to copy
246246 * @param toSpecVersion Version of the SPDX spec the to value complies with
247- * @param toNamespace Namespace to use if an ID needs to be generated for the to object
247+ * @param toNamespace Namespace to use if an ID needs to be generated for the to object - must be a unique prefix to the store
248248 * @return Object URI for the copied object
249249 * @throws InvalidSPDXAnalysisException
250250 */
@@ -258,30 +258,95 @@ public TypedValue copy(IModelStore toStore, IModelStore fromStore,
258258
259259 String toObjectUri = getCopiedObjectUri (fromStore , sourceUri , toStore );
260260 if (Objects .isNull (toObjectUri )) {
261- if (toStore .exists (sourceUri ) || IdType .Anonymous .equals (fromStore .getIdType (sourceUri ))) {
262- // TODO - the toNamspace will never be used - we need to add a from namespace
263- if (Objects .nonNull (toNamespace )) {
264- if (SpdxConstantsCompatV2 .CLASS_EXTERNAL_DOC_REF .equals (type )) {
265- toObjectUri = toNamespace + toStore .getNextId (IdType .DocumentRef );
266- } else {
267- switch (fromStore .getIdType (sourceUri )) {
268- case Anonymous : toObjectUri = toStore .getNextId (IdType .Anonymous ); break ;
269- case LicenseRef : toObjectUri = toNamespace + toStore .getNextId (IdType .LicenseRef ); break ;
270- case DocumentRef : toObjectUri = toNamespace + toStore .getNextId (IdType .DocumentRef ); break ;
271- case SpdxId : toObjectUri = toNamespace + toStore .getNextId (IdType .SpdxId ); break ;
272- case ListedLicense :
273- case Unkown :
274- default : toObjectUri = toStore .getNextId (IdType .Anonymous );
275- }
276- }
277- } else {
278- toObjectUri = toStore .getNextId (IdType .Anonymous );
279- }
280- } else {
281- toObjectUri = sourceUri ;
282- }
261+ toObjectUri = toSpecVersion .startsWith ("SPDX-2" ) ? sourceUriToObjectUriV2Compat (sourceUri ,
262+ fromStore .getIdType (sourceUri ), toStore , toNamespace , SpdxConstantsCompatV2 .CLASS_EXTERNAL_DOC_REF .equals (type )) :
263+ sourceUriToObjectUri (sourceUri , fromStore .getIdType (sourceUri ), toStore , toNamespace );
283264 copy (toStore , toObjectUri , fromStore , sourceUri , type , toSpecVersion , toNamespace );
284265 }
285266 return new TypedValue (toObjectUri , type , toSpecVersion );
286267 }
268+
269+ /**
270+ * @param sourceUri source URI copied from
271+ * @param idType idType from the sourceUri
272+ * @param toStore model store to store the copied item
273+ * @param toNamespace namespace for the generated elements for "to"
274+ * @return an object URI suitable for SPDX V3 and later
275+ * @throws InvalidSPDXAnalysisException
276+ */
277+ private String sourceUriToObjectUri (String sourceUri , IdType idType , IModelStore toStore ,
278+ String toNamespace ) throws InvalidSPDXAnalysisException {
279+ if (IdType .Anonymous .equals (idType )) {
280+ return toStore .getNextId (IdType .Anonymous );
281+ }
282+ if (!toStore .exists (sourceUri )) {
283+ return sourceUri ;
284+ }
285+ if (Objects .isNull (toNamespace ) || toNamespace .isEmpty () ||
286+ sourceUri .startsWith (toNamespace )) {
287+ logger .warn (sourceUri + " already exists - possibly overwriting properties due to a copy from a different model store." );
288+ return sourceUri ;
289+ }
290+ switch (idType ) {
291+ case LicenseRef : return toNamespace + toStore .getNextId (IdType .LicenseRef );
292+ case DocumentRef : return toNamespace + toStore .getNextId (IdType .DocumentRef );
293+ case SpdxId : return toNamespace + toStore .getNextId (IdType .SpdxId );
294+ case ListedLicense : return sourceUri ;
295+ case Anonymous :
296+ case Unkown :
297+ default : return toStore .getNextId (IdType .Anonymous );
298+ }
299+ }
300+
301+ /**
302+ * @param sourceUri source URI copied from
303+ * @param idType idType from the sourceUri
304+ * @param toStore model store to store the copied item
305+ * @param toNamespace namespace for the generated elements for "to"
306+ * @param isExternalDocRef true if the type of the value to be copied is an ExternalDocRef
307+ * @return an object URI suitable for SPDX V2
308+ * @throws InvalidSPDXAnalysisException
309+ */
310+ private String sourceUriToObjectUriV2Compat (String sourceUri , IdType idType ,
311+ IModelStore toStore , String toNamespace , boolean isExternalDocRef ) throws InvalidSPDXAnalysisException {
312+ if ((isExternalDocRef || !(IdType .Anonymous .equals (idType ) ||
313+ IdType .ListedLicense .equals (idType ) || IdType .Unkown .equals (idType )))
314+ && (Objects .isNull (toNamespace ) || toNamespace .isEmpty ())) {
315+ throw new InvalidSPDXAnalysisException ("A to namespace or document URI must be provided to copy SPDX element for SPDX spec version 2" );
316+ }
317+ if (sourceUri .startsWith (toNamespace ) && !toStore .exists (sourceUri )) {
318+ return sourceUri ;
319+ }
320+ if (IdType .ListedLicense .equals (idType )) {
321+ return sourceUri ;
322+ }
323+ String toUri = null ;
324+ if (Objects .nonNull (toNamespace )) {
325+ int poundIndex = sourceUri .lastIndexOf ('#' );
326+ if (poundIndex > 0 ) {
327+ toUri = toNamespace + sourceUri .substring (poundIndex + 1 );
328+ }
329+ }
330+
331+ boolean notNullAndNotExists = Objects .nonNull (toUri ) && !toStore .exists (toUri ); // notExists and nonNull
332+ if (isExternalDocRef ) {
333+ if (!toStore .exists (toUri ) && IdType .DocumentRef .equals (toStore .getIdType (toUri ))) {
334+ return toUri ;
335+ } else {
336+ return toNamespace + toStore .getNextId (IdType .DocumentRef );
337+ }
338+ }
339+ switch (idType ) {
340+ case LicenseRef : return notNullAndNotExists && IdType .LicenseRef .equals (toStore .getIdType (toUri )) ? toUri :
341+ toNamespace + toStore .getNextId (IdType .LicenseRef );
342+ case DocumentRef : return notNullAndNotExists && IdType .DocumentRef .equals (toStore .getIdType (toUri )) ? toUri :
343+ toNamespace + toStore .getNextId (IdType .DocumentRef );
344+ case SpdxId : return notNullAndNotExists && IdType .SpdxId .equals (toStore .getIdType (toUri )) ? toUri :
345+ toNamespace + toStore .getNextId (IdType .SpdxId );
346+ case ListedLicense : return sourceUri ;
347+ case Anonymous :
348+ case Unkown :
349+ default : return toStore .getNextId (IdType .Anonymous );
350+ }
351+ }
287352}
0 commit comments