Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjmisinco2015-08-28 17:14:37 +0000
committerAngel Avila2015-09-12 01:05:34 +0000
commit538384f68f0f14d00c52af1f021984d29a9e51c0 (patch)
tree800f27b90655bc42d5a07a2ca45bc9987e0ff4c2
parent6c68981f8d1ef8cd5e6277dff4ddbf99e5c20eed (diff)
downloadorg.eclipse.osee-538384f68f0f14d00c52af1f021984d29a9e51c0.tar.gz
org.eclipse.osee-538384f68f0f14d00c52af1f021984d29a9e51c0.tar.xz
org.eclipse.osee-538384f68f0f14d00c52af1f021984d29a9e51c0.zip
feature[ats_ATS226476]: Enforce attribute and relation multiplicity in transactions
-rw-r--r--plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/SkynetTransactionTest.java31
-rw-r--r--plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/utils/TestUtil.java4
-rw-r--r--plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/enums/CoreRelationTypes.java36
-rw-r--r--plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/transaction/SkynetTransaction.java49
-rw-r--r--plugins/org.eclipse.osee.orcs.core.test/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImplTest.java68
-rw-r--r--plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImpl.java25
-rw-r--r--plugins/org.eclipse.osee.orcs.test/src/org/eclipse/osee/orcs/api/OrcsTransactionTest.java19
7 files changed, 175 insertions, 57 deletions
diff --git a/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/SkynetTransactionTest.java b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/SkynetTransactionTest.java
index 422f68aaba4..416145493da 100644
--- a/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/SkynetTransactionTest.java
+++ b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/SkynetTransactionTest.java
@@ -20,6 +20,9 @@ import org.eclipse.osee.client.test.framework.OseeLogMonitorRule;
import org.eclipse.osee.client.test.framework.TestInfo;
import org.eclipse.osee.framework.core.data.IOseeBranch;
import org.eclipse.osee.framework.core.enums.CoreArtifactTypes;
+import org.eclipse.osee.framework.core.enums.CoreAttributeTypes;
+import org.eclipse.osee.framework.core.enums.CoreRelationTypes;
+import org.eclipse.osee.framework.jdk.core.type.OseeArgumentException;
import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
import org.eclipse.osee.framework.jdk.core.type.OseeStateException;
import org.eclipse.osee.framework.jdk.core.util.Lib;
@@ -133,6 +136,34 @@ public final class SkynetTransactionTest {
artifact2.purgeFromBranch();
}
+ @Test(expected = OseeStateException.class)
+ public void testAttributeMultiplicity() {
+ Artifact swReq = ArtifactTypeManager.addArtifact(CoreArtifactTypes.SoftwareRequirement, BRANCH);
+ swReq.addAttribute(CoreAttributeTypes.ParagraphNumber, "1.1");
+ swReq.addAttribute(CoreAttributeTypes.ParagraphNumber, "2.2");
+ try {
+ swReq.persist("testAttributeMultiplicity");
+ } finally {
+ swReq.purgeFromBranch();
+ }
+ }
+
+ @Test(expected = OseeArgumentException.class)
+ public void testRelationMultiplicity() {
+ Artifact parent1 = ArtifactTypeManager.addArtifact(CoreArtifactTypes.SoftwareRequirement, BRANCH, "parent1");
+ Artifact parent2 = ArtifactTypeManager.addArtifact(CoreArtifactTypes.SoftwareRequirement, BRANCH, "parent2");
+ Artifact child = ArtifactTypeManager.addArtifact(CoreArtifactTypes.SoftwareRequirement, BRANCH, "child");
+ try {
+ parent1.addRelation(CoreRelationTypes.Default_Hierarchical__Child, child);
+ parent2.addRelation(CoreRelationTypes.Default_Hierarchical__Child, child);
+ child.persist("testRelationMultiplicity");
+ } finally {
+ child.purgeFromBranch();
+ parent1.purgeFromBranch();
+ parent2.purgeFromBranch();
+ }
+ }
+
@Test
public void test_multiThreadedCoModificationOveralappingTransactions() throws Exception {
Object lock = new Object();
diff --git a/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/utils/TestUtil.java b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/utils/TestUtil.java
index 0bf309910cc..d6aa8ad0c83 100644
--- a/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/utils/TestUtil.java
+++ b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/utils/TestUtil.java
@@ -53,7 +53,9 @@ public final class TestUtil {
public static Artifact createSimpleArtifact(IArtifactType artifactType, String name, IOseeBranch branch) throws OseeCoreException {
Artifact softArt = ArtifactTypeManager.addArtifact(artifactType, branch);
softArt.setName(name);
- softArt.addAttribute(CoreAttributeTypes.Subsystem, "Electrical");
+ if (softArt.isAttributeTypeValid(CoreAttributeTypes.Subsystem)) {
+ softArt.setSoleAttributeFromString(CoreAttributeTypes.Subsystem, "Electrical");
+ }
Artifact rootArtifact = OseeSystemArtifacts.getDefaultHierarchyRootArtifact(branch);
rootArtifact.addRelation(CoreRelationTypes.Default_Hierarchical__Child, softArt);
return softArt;
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/enums/CoreRelationTypes.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/enums/CoreRelationTypes.java
index b64f084d3f8..0a7b3d668bf 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/enums/CoreRelationTypes.java
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/enums/CoreRelationTypes.java
@@ -34,51 +34,51 @@ public final class CoreRelationTypes {
public static final IRelationTypeSide Executes__Test_Plan_Element = TokenFactory.createRelationTypeSide(SIDE_A, 0x200000000000015EL, "Executes");
public static final IRelationTypeSide Executes__Test_Procedure = Executes__Test_Plan_Element.getOpposite();
-
+
public static final IRelationTypeSide Related_Feature__Feature = TokenFactory.createRelationTypeSide(SIDE_A, 0x0000000000000058L, "Related Feature");
public static final IRelationTypeSide Related_Feature__Requirement = Related_Feature__Feature.getOpposite();
-
+
public static final IRelationTypeSide Requirement_Trace__Higher_Level = TokenFactory.createRelationTypeSide(SIDE_A, 0x200000000000015FL, "Requirement Trace");
public static final IRelationTypeSide Requirement_Trace__Lower_Level = Requirement_Trace__Higher_Level.getOpposite();
-
+
public static final IRelationTypeSide Safety__Safety_Assessment = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000180L, "Safety Assessment");
public static final IRelationTypeSide Safety__System_Function = Safety__Safety_Assessment.getOpposite();
-
+
public static final IRelationTypeSide Supercedes_Supercedes = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000165L, "Supercedes");
public static final IRelationTypeSide Supercedes_Superceded = Supercedes_Supercedes.getOpposite();
-
+
public static final IRelationTypeSide SupportingInfo_SupportedBy = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000166L, "Supporting Info");
public static final IRelationTypeSide SupportingInfo_SupportingInfo = SupportingInfo_SupportedBy.getOpposite();
-
+
public static final IRelationTypeSide SupportingRequirement__Higher_Level = TokenFactory.createRelationTypeSide(SIDE_A, 0x200000000000017CL, "Supporting Requirement");
public static final IRelationTypeSide SupportingRequirement__Lower_Level = SupportingRequirement__Higher_Level.getOpposite();
-
+
public static final IRelationTypeSide TeamMember_Team = TokenFactory.createRelationTypeSide(SIDE_A, 0x200000000000016AL, "TeamMember");
public static final IRelationTypeSide TeamMember_Member = TeamMember_Team.getOpposite();
-
+
public static final IRelationTypeSide Test_Unit_Result__Test_Unit = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000168L, "Results Data");
public static final IRelationTypeSide Test_Unit_Result__Test_Result = Test_Unit_Result__Test_Unit.getOpposite();
-
+
public static final IRelationTypeSide Universal_Grouping__Group = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000156L, "Universal Grouping");
public static final IRelationTypeSide Universal_Grouping__Members = Universal_Grouping__Group.getOpposite();
-
-
+
+
public static final IRelationTypeSide User_Grouping__Group = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000163L, "User Grouping");
public static final IRelationTypeSide User_Grouping__Members = User_Grouping__Group.getOpposite();
-
-
- public static final IRelationTypeSide Users_Artifact = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000164L, "Artifact");
+
+
+ public static final IRelationTypeSide Users_Artifact = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000164L, "Users");
public static final IRelationTypeSide Users_User = Users_Artifact.getOpposite();
-
+
public static final IRelationTypeSide Uses__Requirement = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000177L, "Uses");
public static final IRelationTypeSide Uses__TestUnit = Uses__Requirement.getOpposite();
-
+
public static final IRelationTypeSide Validation__Requirement = TokenFactory.createRelationTypeSide(SIDE_A, 0x2000000000000160L, "Validation");
public static final IRelationTypeSide Validation__Validator = Validation__Requirement.getOpposite();
-
+
public static final IRelationTypeSide Verification__Requirement = TokenFactory.createRelationTypeSide(SIDE_A, 0x200000000000015BL, "Verification");
public static final IRelationTypeSide Verification__Verifier = Verification__Requirement.getOpposite();
-
+
public static final IRelationTypeSide Verification_Plan__Requirement = TokenFactory.createRelationTypeSide(SIDE_A, 0x200000000000015CL, "Verification Plan");
public static final IRelationTypeSide Verification_Plan__Test_Plan_Element = Verification_Plan__Requirement.getOpposite();
//@formatter:on
diff --git a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/transaction/SkynetTransaction.java b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/transaction/SkynetTransaction.java
index 005eea92874..86ff7755294 100644
--- a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/transaction/SkynetTransaction.java
+++ b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/transaction/SkynetTransaction.java
@@ -25,13 +25,16 @@ import java.util.Set;
import java.util.logging.Level;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.osee.framework.core.data.IOseeBranch;
+import org.eclipse.osee.framework.core.data.TokenFactory;
import org.eclipse.osee.framework.core.enums.ModificationType;
import org.eclipse.osee.framework.core.enums.PermissionEnum;
import org.eclipse.osee.framework.core.enums.RelationSide;
+import org.eclipse.osee.framework.core.enums.RelationTypeMultiplicity;
import org.eclipse.osee.framework.core.model.Branch;
import org.eclipse.osee.framework.core.model.RelationTypeSide;
import org.eclipse.osee.framework.core.model.TransactionRecord;
import org.eclipse.osee.framework.core.model.access.PermissionStatus;
+import org.eclipse.osee.framework.core.model.type.RelationType;
import org.eclipse.osee.framework.core.operation.IOperation;
import org.eclipse.osee.framework.core.operation.Operations;
import org.eclipse.osee.framework.jdk.core.type.CompositeKeyHashMap;
@@ -107,9 +110,8 @@ public final class SkynetTransaction extends TransactionOperation<Branch> {
}
Branch txBranch = getBranch();
if (!artifact.getBranch().equals(txBranch)) {
- String msg =
- String.format("The artifact [%s] is on branch [%s] but this transaction is for branch [%s]",
- artifact.getGuid(), artifact.getBranch(), txBranch);
+ String msg = String.format("The artifact [%s] is on branch [%s] but this transaction is for branch [%s]",
+ artifact.getGuid(), artifact.getBranch(), txBranch);
throw new OseeStateException(msg);
}
@@ -143,8 +145,8 @@ public final class SkynetTransaction extends TransactionOperation<Branch> {
boolean toReturn = true;
if (!UserManager.duringMainUserCreation()) {
Branch fullBranch = BranchManager.getBranch(branch);
- toReturn =
- getAccess().hasBranchPermission(branch, PermissionEnum.WRITE, Level.FINE).matched() && fullBranch.isEditable();
+ toReturn = getAccess().hasBranchPermission(branch, PermissionEnum.WRITE,
+ Level.FINE).matched() && fullBranch.isEditable();
}
return toReturn;
}
@@ -156,16 +158,14 @@ public final class SkynetTransaction extends TransactionOperation<Branch> {
checkBranch(link);
Branch txBranch = getBranch();
if (!link.getBranch().equals(txBranch)) {
- String msg =
- String.format("The relation link [%s] is on branch [%s] but this transaction is for branch [%s]",
- link.getId(), link.getBranch(), txBranch);
+ String msg = String.format("The relation link [%s] is on branch [%s] but this transaction is for branch [%s]",
+ link.getId(), link.getBranch(), txBranch);
throw new OseeStateException(msg);
}
RelationSide sideToCheck = link.getSide(artifact).oppositeSide();
- PermissionStatus status =
- getAccess().canRelationBeModified(artifact, null, new RelationTypeSide(link.getRelationType(), sideToCheck),
- Level.FINE);
+ PermissionStatus status = getAccess().canRelationBeModified(artifact, null,
+ new RelationTypeSide(link.getRelationType(), sideToCheck), Level.FINE);
if (!status.matched()) {
throw new OseeCoreException(
@@ -253,10 +253,36 @@ public final class SkynetTransaction extends TransactionOperation<Branch> {
}
}
+ private void checkMultiplicity(Artifact artifact, Attribute<?> attr) {
+ if (attr.getAttributeType().getMaxOccurrences() == 1 && artifact.getAttributeCount(attr.getAttributeType()) > 1) {
+ throw new OseeStateException("Artifact [%s] can only have 1 [%s] attribute but has %d", artifact.getName(),
+ attr.getAttributeType().getName(), artifact.getAttributeCount(attr.getAttributeType()));
+ }
+ }
+
+ private void checkMultiplicity(Artifact art, RelationLink link) {
+ RelationType relationType = link.getRelationType();
+ RelationTypeMultiplicity multiplicity = relationType.getMultiplicity();
+
+ RelationSide sideToCheck = link.getOppositeSide(art);
+ int limitToCheck = sideToCheck.isSideA() ? multiplicity.getSideALimit() : multiplicity.getSideBLimit();
+ if (limitToCheck == 1) {
+ int count = art.getRelatedArtifactsCount(
+ TokenFactory.createRelationTypeSide(sideToCheck, relationType.getGuid(), relationType.getName()));
+ if (count > 1) {
+ throw new OseeStateException("Artifact [%s] can only have 1 [%s] on [%s] but has %d", art.getName(),
+ link.getSideNameFor(art), sideToCheck.name(), count);
+ }
+ }
+ }
+
private void addAttribute(Artifact artifact, Attribute<?> attribute) throws OseeCoreException {
if (attribute.isDeleted() && !attribute.isInDb()) {
return;
}
+
+ checkMultiplicity(artifact, attribute);
+
if (attribute.getId() == 0) {
attribute.internalSetAttributeId(getNewAttributeId(artifact, attribute));
}
@@ -317,6 +343,7 @@ public final class SkynetTransaction extends TransactionOperation<Branch> {
if (link.isDeleted()) {
return;
}
+ checkMultiplicity(artifact, link);
link.internalSetRelationId(getNewRelationId());
modificationType = NEW;
relationEventType = RelationEventType.Added;
diff --git a/plugins/org.eclipse.osee.orcs.core.test/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImplTest.java b/plugins/org.eclipse.osee.orcs.core.test/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImplTest.java
index d8ff599ae9e..85756734aff 100644
--- a/plugins/org.eclipse.osee.orcs.core.test/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImplTest.java
+++ b/plugins/org.eclipse.osee.orcs.core.test/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImplTest.java
@@ -50,6 +50,7 @@ import org.eclipse.osee.framework.core.model.DefaultBasicArtifact;
import org.eclipse.osee.framework.jdk.core.type.Identifiable;
import org.eclipse.osee.framework.jdk.core.type.OseeArgumentException;
import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
+import org.eclipse.osee.framework.jdk.core.type.OseeStateException;
import org.eclipse.osee.framework.jdk.core.type.ResultSet;
import org.eclipse.osee.framework.jdk.core.util.GUID;
import org.eclipse.osee.logger.Log;
@@ -81,7 +82,7 @@ import org.mockito.stubbing.Answer;
/**
* Test Case for {@link RelationManagerImpl}
- *
+ *
* @author Roberto E. Escobar
*/
public class RelationManagerImplTest {
@@ -96,40 +97,40 @@ public class RelationManagerImplTest {
@Mock private RelationTypeValidity validity;
@Mock private RelationResolver resolver;
@Mock private OrderManagerFactory orderFactory;
-
+
@Mock private RelationFactory relationFactory;
@Mock private OrcsSession session;
@Mock private QueryModuleProvider provider;
@Mock private ProxyProvider proxy;
-
+
@Mock private GraphData graph;
-
+
@Mock private RelationNode node1;
@Mock private RelationNode node2;
@Mock private RelationNode node3;
@Mock private RelationNode node4;
@Mock private RelationNode node5;
@Mock private RelationNode node6;
-
+
@Mock private RelationNodeAdjacencies container1;
@Mock private RelationNodeAdjacencies container2;
-
+
@Mock private IArtifactType artifactType1;
@Mock private IArtifactType artifactType2;
-
+
@Mock private Relation relation1;
@Mock private Relation relation2;
@Mock private Relation relation3;
@Mock private Relation relation4;
-
+
@Mock private IRelationType relType1;
@Mock private IRelationType relType2;
-
+
@Mock private IRelationTypeSide typeAndSide1;
-
+
@Mock private ResultSet<Relation> rSet1;
@Mock private ResultSet<Relation> rSet2;
-
+
@Mock private OrderManager orderManager1;
@Captor private ArgumentCaptor<List<? extends Identifiable<String>>> sortedListCaptor;
// @formatter:on
@@ -489,12 +490,12 @@ public class RelationManagerImplTest {
when(node1.getBranch()).thenReturn(COMMON);
when(node2.getBranch()).thenReturn(COMMON);
- OseeCoreException myException = new OseeCoreException("Test Multiplicity Exception");
+ thrown.expect(OseeStateException.class);
- doThrow(myException).when(validity).checkRelationTypeMultiplicity(TYPE_1, node1, SIDE_B, 1);
+ when(node1.getArtifactType()).thenReturn(artifactType1);
+ when(node2.getArtifactType()).thenReturn(artifactType2);
+ when(validity.getMaximumRelationsAllowed(Default_Hierarchical__Child, artifactType1, SIDE_A)).thenReturn(1);
- thrown.expect(OseeCoreException.class);
- thrown.expectMessage("Test Multiplicity Exception");
manager.relate(session, node1, TYPE_1, node2);
verify(validity).checkRelationTypeValid(TYPE_1, node1, SIDE_A);
@@ -511,12 +512,7 @@ public class RelationManagerImplTest {
when(container1.getResultSet(TYPE_1, INCLUDE_DELETED, node1, SIDE_A)).thenReturn(rSet1);
when(rSet1.getOneOrNull()).thenReturn(relation1);
- OseeCoreException myException = new OseeCoreException("Test Multiplicity Exception");
-
- doThrow(myException).when(validity).checkRelationTypeMultiplicity(TYPE_1, node2, SIDE_A, 1);
-
- thrown.expect(OseeCoreException.class);
- thrown.expectMessage("Test Multiplicity Exception");
+ thrown.expect(OseeStateException.class);
manager.relate(session, node1, TYPE_1, node2);
verify(validity).checkRelationTypeValid(TYPE_1, node1, SIDE_A);
@@ -549,6 +545,11 @@ public class RelationManagerImplTest {
when(relationFactory.createRelation(node1, TYPE_1, node2)).thenReturn(relation1);
when(orderFactory.createOrderManager(node1)).thenReturn(orderManager1);
+ when(node1.getArtifactType()).thenReturn(artifactType1);
+ when(node2.getArtifactType()).thenReturn(artifactType2);
+ when(validity.getMaximumRelationsAllowed(TYPE_1, artifactType1, SIDE_A)).thenReturn(10);
+ when(validity.getMaximumRelationsAllowed(TYPE_1, artifactType2, SIDE_B)).thenReturn(10);
+
manager.relate(session, node1, TYPE_1, node2, LEXICOGRAPHICAL_ASC);
IRelationTypeSide typeSide = RelationUtil.asTypeSide(TYPE_1, SIDE_B);
@@ -576,6 +577,11 @@ public class RelationManagerImplTest {
IRelationTypeSide typeSide = RelationUtil.asTypeSide(TYPE_1, SIDE_B);
when(orderManager1.getSorterId(typeSide)).thenReturn(UNORDERED);
+ when(node1.getArtifactType()).thenReturn(artifactType1);
+ when(node2.getArtifactType()).thenReturn(artifactType2);
+ when(validity.getMaximumRelationsAllowed(TYPE_1, artifactType1, SIDE_A)).thenReturn(10);
+ when(validity.getMaximumRelationsAllowed(TYPE_1, artifactType2, SIDE_B)).thenReturn(10);
+
manager.relate(session, node1, TYPE_1, node2);
verify(container1).getRelation(node1, TYPE_1, node2, INCLUDE_DELETED);
@@ -604,6 +610,11 @@ public class RelationManagerImplTest {
List<RelationNode> nodesToOrder = Arrays.asList(node3, node4, node5, node6);
when(resolver.resolve(session, graph, toOrder, SIDE_B)).thenReturn(nodesToOrder);
+ when(node1.getArtifactType()).thenReturn(artifactType1);
+ when(node2.getArtifactType()).thenReturn(artifactType2);
+ when(validity.getMaximumRelationsAllowed(TYPE_1, artifactType1, SIDE_A)).thenReturn(10);
+ when(validity.getMaximumRelationsAllowed(TYPE_1, artifactType2, SIDE_B)).thenReturn(10);
+
manager.relate(session, node1, TYPE_1, node2, USER_DEFINED);
verify(container1).getRelation(node1, TYPE_1, node2, INCLUDE_DELETED);
@@ -639,6 +650,11 @@ public class RelationManagerImplTest {
when(orderFactory.createOrderManager(node1)).thenReturn(orderManager1);
when(orderManager1.getSorterId(Default_Hierarchical__Child)).thenReturn(UNORDERED);
+ when(node1.getArtifactType()).thenReturn(artifactType1);
+ when(node2.getArtifactType()).thenReturn(artifactType2);
+ when(validity.getMaximumRelationsAllowed(Default_Hierarchical__Child, artifactType1, SIDE_A)).thenReturn(10);
+ when(validity.getMaximumRelationsAllowed(Default_Hierarchical__Child, artifactType2, SIDE_B)).thenReturn(10);
+
manager.addChild(session, node1, node2);
verify(container1).getRelation(node1, DEFAULT_HIERARCHY, node2, INCLUDE_DELETED);
@@ -661,6 +677,11 @@ public class RelationManagerImplTest {
when(orderFactory.createOrderManager(node1)).thenReturn(orderManager1);
when(orderManager1.getSorterId(Default_Hierarchical__Child)).thenReturn(UNORDERED);
+ when(node1.getArtifactType()).thenReturn(artifactType1);
+ when(node2.getArtifactType()).thenReturn(artifactType2);
+ when(validity.getMaximumRelationsAllowed(Default_Hierarchical__Child, artifactType1, SIDE_A)).thenReturn(10);
+ when(validity.getMaximumRelationsAllowed(Default_Hierarchical__Child, artifactType2, SIDE_B)).thenReturn(10);
+
List<? extends RelationNode> children = Arrays.asList(node2);
manager.addChildren(session, node1, children);
@@ -686,6 +707,11 @@ public class RelationManagerImplTest {
when(orderFactory.createOrderManager(node1)).thenReturn(orderManager1);
when(orderManager1.getSorterId(Default_Hierarchical__Child)).thenReturn(UNORDERED);
+ when(node1.getArtifactType()).thenReturn(artifactType1);
+ when(node2.getArtifactType()).thenReturn(artifactType2);
+ when(validity.getMaximumRelationsAllowed(Default_Hierarchical__Child, artifactType1, SIDE_A)).thenReturn(10);
+ when(validity.getMaximumRelationsAllowed(Default_Hierarchical__Child, artifactType2, SIDE_B)).thenReturn(10);
+
manager.addChild(session, node1, node2);
verify(orderManager1).getSorterId(Default_Hierarchical__Child);
diff --git a/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImpl.java b/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImpl.java
index 4f5732a1750..c673fb10eba 100644
--- a/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImpl.java
+++ b/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/relation/impl/RelationManagerImpl.java
@@ -41,6 +41,7 @@ import org.eclipse.osee.framework.core.enums.RelationOrderBaseTypes;
import org.eclipse.osee.framework.core.enums.RelationSide;
import org.eclipse.osee.framework.jdk.core.type.Identifiable;
import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
+import org.eclipse.osee.framework.jdk.core.type.OseeStateException;
import org.eclipse.osee.framework.jdk.core.type.ResultSet;
import org.eclipse.osee.framework.jdk.core.type.ResultSets;
import org.eclipse.osee.framework.jdk.core.util.Conditions;
@@ -231,8 +232,7 @@ public class RelationManagerImpl implements RelationManager {
validity.checkRelationTypeValid(type, bNode, SIDE_B);
// Check we can create the type on other side of each node
- checkMultiplicityCanAdd(session, type, aNode, SIDE_B);
- checkMultiplicityCanAdd(session, type, bNode, SIDE_A);
+ checkMultiplicityCanAdd(session, type, aNode, bNode);
Relation relation = getRelation(session, aNode, type, bNode, INCLUDE_DELETED).getOneOrNull();
boolean updated = false;
@@ -257,9 +257,22 @@ public class RelationManagerImpl implements RelationManager {
return aNode.getGraph().getTransaction() > bNode.getGraph().getTransaction() ? aNode.getGraph() : bNode.getGraph();
}
- private void checkMultiplicityCanAdd(OrcsSession session, IRelationType type, RelationNode node, RelationSide side) throws OseeCoreException {
- int currentCount = getRelatedCount(session, type, node, side);
- validity.checkRelationTypeMultiplicity(type, node, side, currentCount + 1);
+ private void checkMultiplicityCanAdd(OrcsSession session, IRelationType type, RelationNode aNode, RelationNode bNode) {
+ int bSideCount = getRelations(session, type, aNode, SIDE_A, EXCLUDE_DELETED).size();
+ int bSideMax = validity.getMaximumRelationsAllowed(type, bNode.getArtifactType(), SIDE_B);
+
+ if (bSideCount >= bSideMax) {
+ throw new OseeStateException("Relation type [%s] on [%s] exceeds max occurrence rule on [%s]", type.getName(),
+ SIDE_B, aNode.getExceptionString());
+ }
+
+ int aSideCount = getRelations(session, type, bNode, SIDE_B, EXCLUDE_DELETED).size();
+ int aSideMax = validity.getMaximumRelationsAllowed(type, aNode.getArtifactType(), SIDE_A);
+
+ if (aSideCount >= aSideMax) {
+ throw new OseeStateException("Relation type [%s] on [%s] exceeds max occurrence rule on [%s]", type.getName(),
+ SIDE_A, bNode.getExceptionString());
+ }
}
///////////////////////// UNRELATE NODES ///////////////////
@@ -490,7 +503,7 @@ public class RelationManagerImpl implements RelationManager {
int artIdA = rel.getOrcsData().getArtIdA();
int artIdB = rel.getOrcsData().getArtIdB();
int checkArtId = destination.getLocalId() == artIdA ? artIdB : artIdA;
- // need to check if artifact to relate to exists
+ // need to check if artifact to relate to exists
ArtifactReadable readable =
provider.getQueryFactory(session).fromBranch(branch).andUuid(checkArtId).getResults().getOneOrNull();
return readable;
diff --git a/plugins/org.eclipse.osee.orcs.test/src/org/eclipse/osee/orcs/api/OrcsTransactionTest.java b/plugins/org.eclipse.osee.orcs.test/src/org/eclipse/osee/orcs/api/OrcsTransactionTest.java
index e94d2b8b11e..75326178a9e 100644
--- a/plugins/org.eclipse.osee.orcs.test/src/org/eclipse/osee/orcs/api/OrcsTransactionTest.java
+++ b/plugins/org.eclipse.osee.orcs.test/src/org/eclipse/osee/orcs/api/OrcsTransactionTest.java
@@ -41,6 +41,7 @@ import org.eclipse.osee.framework.core.enums.SystemUser;
import org.eclipse.osee.framework.core.enums.TransactionDetailsType;
import org.eclipse.osee.framework.jdk.core.type.OseeArgumentException;
import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
+import org.eclipse.osee.framework.jdk.core.type.OseeStateException;
import org.eclipse.osee.framework.jdk.core.type.ResultSet;
import org.eclipse.osee.framework.jdk.core.util.Lib;
import org.eclipse.osee.orcs.OrcsApi;
@@ -1075,6 +1076,24 @@ public class OrcsTransactionTest {
assertEquals(expectedComment, actual.getComment());
}
+ @Test(expected = OseeStateException.class)
+ public void testAttributeMultiplicity() {
+ TransactionBuilder tx = createTx();
+ ArtifactId art1 = tx.createArtifact(CoreArtifactTypes.SoftwareRequirement, "SwReq");
+ tx.createAttribute(art1, CoreAttributeTypes.ParagraphNumber, "1.1");
+ tx.createAttribute(art1, CoreAttributeTypes.ParagraphNumber, "2.2");
+ }
+
+ @Test(expected = OseeStateException.class)
+ public void testRelationMultiplicity() {
+ TransactionBuilder tx = createTx();
+ ArtifactId child = tx.createArtifact(CoreArtifactTypes.SoftwareRequirement, "Child");
+ ArtifactId parent1 = tx.createArtifact(CoreArtifactTypes.SoftwareRequirement, "Parent1");
+ ArtifactId parent2 = tx.createArtifact(CoreArtifactTypes.SoftwareRequirement, "Parent2");
+ tx.relate(parent1, Default_Hierarchical__Parent, child);
+ tx.relate(parent2, Default_Hierarchical__Parent, child);
+ }
+
private TransactionBuilder createTx() throws OseeCoreException {
return txFactory.createTransaction(COMMON, userArtifact, testName.getMethodName());
}

Back to the top