expanded NoGUIDException to include an assignment exception and a base to both exceptions; tests modified

This commit is contained in:
FateJH 2020-01-09 03:09:14 -05:00 committed by pschord
parent d43d94377b
commit ad2acc13c4
5 changed files with 108 additions and 31 deletions

View file

@ -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))
}

View file

@ -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)
}
}

View file

@ -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)

View file

@ -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!
}
}

View file

@ -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 {