From ad2acc13c4de88ec6020a395ca5d2eec1226efbb Mon Sep 17 00:00:00 2001 From: FateJH Date: Thu, 9 Jan 2020 03:09:14 -0500 Subject: [PATCH] expanded NoGUIDException to include an assignment exception and a base to both exceptions; tests modified --- .../objects/entity/GUIDException.scala | 55 +++++++++++++++++++ .../objects/entity/IdentifiableEntity.scala | 38 ++++++++----- .../objects/entity/NoGUIDException.scala | 6 -- .../objects/guid/NumberPoolHub.scala | 2 +- .../src/test/scala/objects/EntityTest.scala | 38 +++++++++---- 5 files changed, 108 insertions(+), 31 deletions(-) create mode 100644 common/src/main/scala/net/psforever/objects/entity/GUIDException.scala delete mode 100644 common/src/main/scala/net/psforever/objects/entity/NoGUIDException.scala diff --git a/common/src/main/scala/net/psforever/objects/entity/GUIDException.scala b/common/src/main/scala/net/psforever/objects/entity/GUIDException.scala new file mode 100644 index 00000000..f1842ca4 --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/entity/GUIDException.scala @@ -0,0 +1,55 @@ +// Copyright (c) 2017-2020 PSForever +package net.psforever.objects.entity + +import net.psforever.types.PlanetSideGUID + +/** + * The base for all complaints that can be raised regarding the management of global unique identifier numbers. + * @param message the message string + * @param cause the cause of this error + * @param obj the entity being manipulated when the complaint arose + * @param guid the identifier number being manipulated when the ciomplaint arose + */ +abstract class GUIDException(message : String, cause : Throwable, obj : IdentifiableEntity, guid : PlanetSideGUID) + extends RuntimeException(message, cause) { + private val entity : IdentifiableEntity = obj + def getEntity : IdentifiableEntity = entity + + private val entityGUID : PlanetSideGUID = guid + def getGUID : PlanetSideGUID = entityGUID +} + +/** + * The specific complaint for an instance where an entity does not possess a global unique identifier number + * but the said number is requested. + * In general, this `Exception` is only thrown if the entity has never been registered, + * or provided the bare minimum or registration benefits. + * @param message the message string + * @param obj the entity being manipulated when the complaint arose + * @param cause the cause of this error + */ +class NoGUIDException(message : String, + obj : IdentifiableEntity = None.orNull, + cause : Throwable = None.orNull + ) extends GUIDException(message, cause, obj, null) + +object NoGUIDException { + def unapply(e : NoGUIDException): Option[(String, IdentifiableEntity, Throwable)] = Some((e.getMessage, e.getEntity, e.getCause)) +} + +/** + * The general complaint for an instance where an entity can not be assigned the given global unique identifier number. + * @param message the message string + * @param obj the entity being manipulated when the complaint arose + * @param guid the identifier number being manipulated when the ciomplaint arose + * @param cause the cause of this error + */ +class AssigningGUIDException(message : String, + obj : IdentifiableEntity, + guid : PlanetSideGUID, + cause : Throwable = None.orNull + ) extends GUIDException(message, cause, obj, guid) + +object AssigningGUIDException { + def unapply(e : AssigningGUIDException): Option[(String, Throwable, IdentifiableEntity, PlanetSideGUID)] = Some((e.getMessage, e.getCause, e.getEntity, e.getGUID)) +} diff --git a/common/src/main/scala/net/psforever/objects/entity/IdentifiableEntity.scala b/common/src/main/scala/net/psforever/objects/entity/IdentifiableEntity.scala index 0a9489f9..0c9669b3 100644 --- a/common/src/main/scala/net/psforever/objects/entity/IdentifiableEntity.scala +++ b/common/src/main/scala/net/psforever/objects/entity/IdentifiableEntity.scala @@ -33,14 +33,21 @@ abstract class IdentifiableEntity extends Identifiable { /** indicate the validity of the current GUID */ private var guidValid : Boolean = false /** the current accessor; can be re-assigned */ - private var guidAccessor : IdentifiableEntity=>PlanetSideGUID = IdentifiableEntity.noGuidGet + private var guidAccessor : IdentifiableEntity=>PlanetSideGUID = IdentifiableEntity.getWhenNoGUID /** the current mutator; can be re-assigned */ - private var guidMutator : (IdentifiableEntity, PlanetSideGUID)=>PlanetSideGUID = IdentifiableEntity.noGuidSet + private var guidMutator : (IdentifiableEntity, PlanetSideGUID)=>PlanetSideGUID = IdentifiableEntity.setWhenNoGUID def GUID : PlanetSideGUID = guidAccessor(this) - /** Always intercept `StalePlanetSideGUID` references when attempting to mutate the GUID value. */ - def GUID_=(guid : StalePlanetSideGUID) : PlanetSideGUID = guidAccessor(this) + /** + * Always intercept `StalePlanetSideGUID` references when attempting to mutate the GUID value. + * @param guid the valid GUID to assign + * @throws `AssigningGUIDException` always + * @return never returns + */ + def GUID_=(guid : StalePlanetSideGUID) : PlanetSideGUID = { + throw new AssigningGUIDException(s"attempting to assign a stale global identifier to an entity", this, guid) + } def GUID_=(guid : PlanetSideGUID) : PlanetSideGUID = guidMutator(this, guid) @@ -59,7 +66,7 @@ abstract class IdentifiableEntity extends Identifiable { def Invalidate() : Unit = { guidValid = false current = StalePlanetSideGUID(current.guid) - guidMutator = IdentifiableEntity.noGuidSet + guidMutator = IdentifiableEntity.setWhenNoGUID } } @@ -70,8 +77,8 @@ object IdentifiableEntity { * @throws `NoGUIDException` always * @return never returns */ - def noGuidGet(o : IdentifiableEntity) : PlanetSideGUID = { - throw NoGUIDException(s"did not initialize this object $o with a valid global identifier") + def getWhenNoGUID(o : IdentifiableEntity) : PlanetSideGUID = { + throw new NoGUIDException(s"did not initialize this object $o with a valid global identifier") } /** @@ -83,11 +90,11 @@ object IdentifiableEntity { * @param guid the valid GUID to assign * @return the GUID */ - def noGuidSet(o : IdentifiableEntity, guid : PlanetSideGUID) : PlanetSideGUID = { + def setWhenNoGUID(o : IdentifiableEntity, guid : PlanetSideGUID) : PlanetSideGUID = { o.current = guid o.guidValid = true - o.guidAccessor = guidGet - o.guidMutator = guidSet + o.guidAccessor = getWhenValidGUID + o.guidMutator = setWhenValidGUID guid } @@ -96,15 +103,18 @@ object IdentifiableEntity { * @param o the entity * @return the entity's GUID */ - def guidGet(o : IdentifiableEntity) : PlanetSideGUID = o.current + def getWhenValidGUID(o : IdentifiableEntity) : PlanetSideGUID = o.current /** * The entity is in a condition where it can not be assigned the new valid GUID. * This state establishes itself after setting the very first valid GUID and - * will persist to the end of the entity's life. + * will persist until the entity is invalidated. * @param o the any entity with a GUID * @param guid the valid GUID to assign - * @return the entity's GUID + * @throws `AssigningGUIDException` always + * @return never returns */ - def guidSet(o : IdentifiableEntity, guid : PlanetSideGUID) : PlanetSideGUID = o.current + def setWhenValidGUID(o : IdentifiableEntity, guid : PlanetSideGUID) : PlanetSideGUID = { + throw new AssigningGUIDException("attempting to set GUID to already valid object; try invalidating it", o, guid) + } } diff --git a/common/src/main/scala/net/psforever/objects/entity/NoGUIDException.scala b/common/src/main/scala/net/psforever/objects/entity/NoGUIDException.scala deleted file mode 100644 index 9685b27a..00000000 --- a/common/src/main/scala/net/psforever/objects/entity/NoGUIDException.scala +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) 2017 PSForever -package net.psforever.objects.entity - -case class NoGUIDException(private val message: String = "", - private val cause: Throwable = None.orNull - ) extends RuntimeException(message, cause) diff --git a/common/src/main/scala/net/psforever/objects/guid/NumberPoolHub.scala b/common/src/main/scala/net/psforever/objects/guid/NumberPoolHub.scala index 66712417..4b79dae4 100644 --- a/common/src/main/scala/net/psforever/objects/guid/NumberPoolHub.scala +++ b/common/src/main/scala/net/psforever/objects/guid/NumberPoolHub.scala @@ -285,7 +285,7 @@ class NumberPoolHub(private val source : NumberSource) { case Success(key) => Success(key) case Failure(_) => - throw NoGUIDException(s"a pool gave us a number $number that is actually unavailable") //stop the show; this is terrible! + throw new NoGUIDException(s"a pool gave us a number $number that is actually unavailable") //stop the show; this is terrible! } } diff --git a/common/src/test/scala/objects/EntityTest.scala b/common/src/test/scala/objects/EntityTest.scala index b175611f..5636ac7e 100644 --- a/common/src/test/scala/objects/EntityTest.scala +++ b/common/src/test/scala/objects/EntityTest.scala @@ -3,7 +3,7 @@ package objects import net.psforever.objects.PlanetSideGameObject import net.psforever.objects.definition.ObjectDefinition -import net.psforever.objects.entity.NoGUIDException +import net.psforever.objects.entity.{AssigningGUIDException, NoGUIDException} import net.psforever.types.{PlanetSideGUID, StalePlanetSideGUID, ValidPlanetSideGUID, Vector3} import org.specs2.mutable._ @@ -151,7 +151,14 @@ class EntityTest extends Specification { "error if set to an invalid GUID before being set to a valid GUID" in { val obj : EntityTestClass = new EntityTestClass obj.GUID must throwA[NoGUIDException] - (obj.GUID = StalePlanetSideGUID(1)) must throwA[NoGUIDException] + try { + obj.GUID = StalePlanetSideGUID(1) + ko + } + catch { + case AssigningGUIDException(_, _, _, _ : StalePlanetSideGUID) => ok + case _ : Throwable => ko + } } "work after valid mutation" in { @@ -160,20 +167,32 @@ class EntityTest extends Specification { obj.GUID mustEqual PlanetSideGUID(1051) } - "ignore subsequent mutations using a valid GUID" in { + "raise complaint about subsequent mutations using a valid GUID" in { val obj : EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) - obj.GUID = ValidPlanetSideGUID(1) - obj.GUID mustEqual PlanetSideGUID(1051) + try { + obj.GUID = ValidPlanetSideGUID(1) + ko + } + catch { + case AssigningGUIDException(_, _, _, ValidPlanetSideGUID(1)) => ok + case _ : Throwable => ko + } } "ignore subsequent mutations using an invalid GUID" in { val obj : EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) - obj.GUID = StalePlanetSideGUID(1) - obj.GUID mustEqual PlanetSideGUID(1051) + try { + obj.GUID = StalePlanetSideGUID(1) + ko + } + catch { + case AssigningGUIDException(_, _, _, _ : StalePlanetSideGUID) => ok + case _ : Throwable => ko + } } "invalidate does nothing by default" in { @@ -192,7 +211,7 @@ class EntityTest extends Specification { obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true } - "setting an invalid GUID after invalidating the previous valid mutation returns the same" in { + "setting an invalid GUID after invalidating the previous valid mutation still raises complaint" in { val obj : EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) @@ -200,9 +219,8 @@ class EntityTest extends Specification { obj.Invalidate() obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true - obj.GUID = StalePlanetSideGUID(2) + (obj.GUID = StalePlanetSideGUID(2)) must throwA[AssigningGUIDException] obj.GUID mustEqual PlanetSideGUID(1051) - obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true } "setting a valid GUID after invalidating correctly sets the new valid GUID" in {