eclipse-capella / capella-requirements-vp

This add-on allows importing a set of requirements from a ReqIF file
Eclipse Public License 2.0
18 stars 15 forks source link

Support ReqIF.ForeignID values which cannot be cast to integers #178

Open jdess opened 1 year ago

jdess commented 1 year ago

Hi,

when importing ReqIF files where the ReqIF.ForeignID value is not a valid integer, the import fails with the following stack trace:

java.lang.ClassCastException: class java.lang.String cannot be cast to class java.math.BigInteger (java.lang.String and java.math.BigInteger are in module java.base of loader 'bootstrap') at org.polarsys.kitalpha.vp.requirements.Requirements.impl.RequirementImpl.eSet(RequirementImpl.java:533) at org.polarsys.kitalpha.vp.requirements.Requirements.impl.FolderImpl.eSet(FolderImpl.java:137) at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eSet(BasicEObjectImpl.java:1110) at org.polarsys.capella.vp.requirements.importer.transposer.bridge.ReqIFMapping.setAttribute(ReqIFMapping.java:319) at org.polarsys.capella.vp.requirements.importer.transposer.bridge.ReqIFMapping.parseStandardReqIFAttributes(ReqIFMapping.java:418) at org.polarsys.capella.vp.requirements.importer.transposer.bridge.rules.FolderRule.createTarget(FolderRule.java:45) at org.polarsys.capella.vp.requirements.importer.transposer.bridge.rules.FolderRule.createTarget(FolderRule.java:1) at org.eclipse.emf.diffmerge.bridge.mapping.operations.MappingBridgeOperation.handleRuleForTargetCreation(MappingBridgeOperation.java:223) at org.eclipse.emf.diffmerge.bridge.mapping.operations.MappingBridgeOperation.handleQueryForTargetCreation(MappingBridgeOperation.java:196) at org.eclipse.emf.diffmerge.bridge.mapping.operations.MappingBridgeOperation.handleQueryForTargetCreationRec(MappingBridgeOperation.java:172) at org.eclipse.emf.diffmerge.bridge.mapping.operations.MappingBridgeOperation.handleQueriesForTargetCreationRec(MappingBridgeOperation.java:140) at org.eclipse.emf.diffmerge.bridge.mapping.operations.MappingBridgeOperation.handleBridge(MappingBridgeOperation.java:109) at org.polarsys.capella.vp.requirements.importer.transposer.bridge.ReqIfMappingBridgeOperation.access$0(ReqIfMappingBridgeOperation.java:1) at org.polarsys.capella.vp.requirements.importer.transposer.bridge.ReqIfMappingBridgeOperation$1.run(ReqIfMappingBridgeOperation.java:50) at org.polarsys.capella.common.ef.ExecutionManager$2.doExecute(ExecutionManager.java:129) at org.eclipse.emf.transaction.RecordingCommand.execute(RecordingCommand.java:135) at org.eclipse.emf.workspace.EMFCommandOperation.doExecute(EMFCommandOperation.java:119) at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:150) at org.eclipse.core.commands.operations.DefaultOperationHistory.execute(DefaultOperationHistory.java:496) at org.polarsys.capella.common.ef.internal.command.WorkspaceCommandStackImpl.doExecute(WorkspaceCommandStackImpl.java:150) at org.polarsys.capella.common.platform.sirius.ted.SemanticEditingDomainFactory$SemanticCommandStack.doExecute(SemanticEditingDomainFactory.java:277) at org.eclipse.emf.transaction.impl.AbstractTransactionalCommandStack.execute(AbstractTransactionalCommandStack.java:165) at org.polarsys.capella.common.ef.ExecutionManager.executeReadWriteCommand(ExecutionManager.java:93) at org.polarsys.capella.common.ef.ExecutionManager.execute(ExecutionManager.java:68) at org.polarsys.capella.vp.requirements.importer.transposer.bridge.ReqIfMappingBridgeOperation.handleBridge(ReqIfMappingBridgeOperation.java:46) at org.eclipse.emf.diffmerge.bridge.mapping.operations.MappingBridgeOperation.run(MappingBridgeOperation.java:307) at org.polarsys.capella.vp.requirements.importer.transposer.bridge.ReqIfMappingBridgeOperation.run(ReqIfMappingBridgeOperation.java:88) at org.eclipse.emf.diffmerge.generic.impl.helpers.AbstractExpensiveOperation.run(AbstractExpensiveOperation.java:66) at org.eclipse.emf.diffmerge.bridge.mapping.impl.MappingBridge.executeOn(MappingBridge.java:92) at org.eclipse.emf.diffmerge.bridge.mapping.impl.MappingBridge.executeOn(MappingBridge.java:1) at org.eclipse.emf.diffmerge.bridge.operations.IncrementalWrappingBridgeOperation.run(IncrementalWrappingBridgeOperation.java:115) at org.eclipse.emf.diffmerge.generic.impl.helpers.AbstractExpensiveOperation.run(AbstractExpensiveOperation.java:66) at org.eclipse.emf.diffmerge.bridge.impl.emf.AbstractWrappingIncrementalBridge.executeOn(AbstractWrappingIncrementalBridge.java:90) at org.polarsys.capella.vp.requirements.importer.transposer.activities.InitializeTransformation.initializeTransformation(InitializeTransformation.java:124) at org.polarsys.capella.vp.requirements.importer.transposer.activities.InitializeTransformation$1.run(InitializeTransformation.java:85) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

This causes issues when importing ReqIF files which were exported from Polarion. The Polarion export adds the ID prefix to the foreign ID by default (e.g. as "PREFIX-123"). Reading through https://community.sw.siemens.com/s/question/0D54O00006n587WSAQ/how-can-i-import-doors-module-prefixes-via-reqif, it seems like other tools like DOORS split the prefix and ID into different fields which is why the import works fine. However, it would be great if the add-on accepted non-numeric foreign IDs like the prefixed IDs.

Expected behavior: The ReqIF import accepts string values for the ReqIF.ForeignID field so that it can also support non-numeric or prefixed foreign IDs.

liborbus commented 1 year ago

The same problem appears with import of ReqIF files exported from ReqView which uses string requirement IDs with document ID prefix (e.g. NEEDS-123), see ReqView - Export ReqIF to MBSE Tools. As a workaround you can disable import of ReqIF.ForeignID in Capella > Requirements > Importer preferences. However, this workaround results in lost traceability from to requirements.

jdess commented 1 year ago

Thank you, seems like Polarion is not that exotic, then. I agree with your workaround, that matches how we patched it for now.

At least for Polarion, an enhancement to your workaround which kind of restores the traceability is to also export the Item URL field. With that, you can extract the foreign ID again when displaying the requirements. The URL to the requirements in Polarion is typically a string like the one below:

https://{URL to polarion server, project and document}?selection={foreign ID}

Which you can then use to extract the foreign ID and concatenate it with the title of the requirement using AQL as shown below:

aql:'[' + self.ownedAttributes->select(a | a.definition.ReqIFLongName == 'Item URL')->first().value.replace('.*selection=', '') + '] ' + self.ReqIFChapterName

This will then give you the requirement label:

[{foreign ID}] {requirement title}, e.g. [REQ-123] Some requirement description

You can place this AQL string at different locations as you see fit, see https://forum.mbse-capella.org/t/custom-requirement-diagram/5537/14