2020import java .util .ArrayList ;
2121import java .util .Collection ;
2222import java .util .Collections ;
23+ import java .util .HashSet ;
2324import java .util .Iterator ;
2425import java .util .List ;
2526import java .util .Objects ;
2627import java .util .Optional ;
28+ import java .util .Set ;
2729
2830import javax .annotation .Nullable ;
2931
3234import org .spdx .library .InvalidSPDXAnalysisException ;
3335import org .spdx .library .SpdxConstants ;
3436import org .spdx .library .model .enumerations .RelationshipType ;
37+ import org .spdx .storage .IModelStore ;
38+ import org .spdx .storage .IModelStore .IModelStoreLock ;
3539
3640/**
3741 * Collection of SPDX elements related to an SpdxElement
@@ -50,6 +54,10 @@ public class RelatedElementCollection implements Collection<SpdxElement> {
5054 ModelCollection <Relationship > relationshipCollection ;
5155 private RelationshipType relationshipTypeFilter ;
5256 private String relatedElementTypeFilter ;
57+ /**
58+ * Keeps track of any created relationships so we can delete them when removed
59+ */
60+ private Set <String > createdRelationshipIds = new HashSet <>();
5361
5462 private SpdxElement owningElement ;
5563
@@ -170,8 +178,15 @@ public boolean add(SpdxElement e) {
170178 return false ;
171179 }
172180 try {
173- Relationship relationship = owningElement .createRelationship (e , relationshipTypeFilter , null );
174- return owningElement .addRelationship (relationship );
181+ IModelStoreLock lock = owningElement .getModelStore ()
182+ .enterCriticalSection (owningElement .getDocumentUri (), false );
183+ try {
184+ Relationship relationship = owningElement .createRelationship (e , relationshipTypeFilter , null );
185+ createdRelationshipIds .add (relationship .getId ());
186+ return owningElement .addRelationship (relationship );
187+ } finally {
188+ owningElement .getModelStore ().leaveCriticalSection (lock );
189+ }
175190 } catch (InvalidSPDXAnalysisException e1 ) {
176191 logger .error ("Error adding relationship" ,e1 );
177192 throw new RuntimeException (e1 );
@@ -199,7 +214,28 @@ public boolean remove(Object o) {
199214 if (relatedElement .isPresent () &&
200215 relatedElement .get ().equals (o ) &&
201216 relationship .getRelationshipType ().equals (relationshipTypeFilter )) {
202- return relationshipCollection .remove (relationship );
217+ IModelStore modelStore = relationship .getModelStore ();
218+ String documentUri = relationship .getDocumentUri ();
219+ final IModelStoreLock lock = modelStore .enterCriticalSection (documentUri , false );
220+ try {
221+ if (relationshipCollection .remove (relationship )) {
222+ try {
223+ if (createdRelationshipIds .contains (relationship .getId ())) {
224+ createdRelationshipIds .remove (relationship .getId ());
225+ modelStore .delete (documentUri , relationship .getId ());
226+ }
227+ } catch (SpdxIdInUseException ex ) {
228+ // This is possible if the relationship is in use
229+ // outside of the RelatedElementCollection - just ignore
230+ // the exception
231+ }
232+ return true ;
233+ } else {
234+ return false ;
235+ }
236+ } finally {
237+ modelStore .leaveCriticalSection (lock );
238+ }
203239 }
204240 } catch (InvalidSPDXAnalysisException e ) {
205241 logger .error ("Error getting relationship properties - skipping removal of element" ,e );
0 commit comments