From ce6d86d344de78bf4b631c1f6d4b4cc3222ba2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Wed, 18 Jan 2012 09:28:35 +0100 Subject: [PATCH] Planet resources and resource providers in XML dumps * Dump version bumped up to 2 * Added SQL view that shows resource delta and provider information for all empire-owned planets * Added new storage classes for resource providers and resource deltas * Added row mapper which extracts all planet resources information (providers and deltas) * Modified dump generator to include planet resources / resource providers --- .../lw/beans/bt/es/EmpireSummaryBean.java | 219 +++++++++++++++--- .../lw/beans/bt/es/PlanetResourceRow.java | 96 ++++++++ .../lw/beans/bt/es/ResourceRowMapper.java | 58 +++++ .../lw/beans/bt/es/data/DebugInformation.java | 2 +- .../es/data/InvalidDumpContentsException.java | 60 +++++ .../beans/bt/es/data/PlanetInformation.java | 130 +++++++++-- .../bt/es/data/ResourceDeltaInformation.java | 109 +++++++++ .../es/data/ResourceProviderInformation.java | 152 ++++++++++++ .../parts/040-functions/200-bugs.sql | 48 ++++ .../010-dump-planet-resources-view.sql | 73 ++++++ .../010-dump-planet-resources-view.sql | 11 + .../bt/es/TestBuildingsInformationMapper.java | 2 + .../lw/beans/bt/es/TestPlanetResourceRow.java | 102 ++++++++ .../lw/beans/bt/es/TestResourceRowMapper.java | 129 +++++++++++ .../TestInvalidDumpContentsException.java | 85 +++++++ .../es/data/TestResourceDeltaInformation.java | 174 ++++++++++++++ .../data/TestResourceProviderInformation.java | 207 +++++++++++++++++ 17 files changed, 1607 insertions(+), 50 deletions(-) create mode 100644 legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetResourceRow.java create mode 100644 legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResourceRowMapper.java create mode 100644 legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/InvalidDumpContentsException.java create mode 100644 legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceDeltaInformation.java create mode 100644 legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceProviderInformation.java create mode 100644 legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/010-dump-planet-resources-view.sql create mode 100644 legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/010-dump-planet-resources-view.sql create mode 100644 legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestPlanetResourceRow.java create mode 100644 legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestResourceRowMapper.java create mode 100644 legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestInvalidDumpContentsException.java create mode 100644 legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceDeltaInformation.java create mode 100644 legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceProviderInformation.java diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireSummaryBean.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireSummaryBean.java index d61469b..bc2fa7d 100644 --- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireSummaryBean.java +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireSummaryBean.java @@ -20,6 +20,8 @@ import com.deepclone.lw.beans.bt.es.data.PlanetInformation; import com.deepclone.lw.beans.bt.es.data.QueueInformation; import com.deepclone.lw.beans.bt.es.data.QueueItemInformation; import com.deepclone.lw.beans.bt.es.data.ResearchInformation; +import com.deepclone.lw.beans.bt.es.data.ResourceDeltaInformation; +import com.deepclone.lw.beans.bt.es.data.ResourceProviderInformation; import com.deepclone.lw.beans.bt.es.data.ShipsInformation; import com.deepclone.lw.beans.bt.es.data.SystemInformation; import com.deepclone.lw.interfaces.bt.EmpireSummary; @@ -40,6 +42,36 @@ import com.thoughtworks.xstream.XStream; public class EmpireSummaryBean implements EmpireSummary { + /** Beginning of all dump SQL queries */ + private static final String SQL_START = "SELECT * FROM bugs.dump_"; + + /** Ending of (almost) all dump SQL queries */ + private static final String SQL_END = "_view WHERE empire_id = ?"; + + /** SQL query that accesses the main empire dump view */ + private static final String Q_EMPIRE = SQL_START + "main" + SQL_END; + + /** SQL query that accesses the research dump view */ + private static final String Q_RESEARCH = SQL_START + "research" + SQL_END; + + /** SQL query that accesses the empire's planets dump view */ + private static final String Q_PLANETS = SQL_START + "planets" + SQL_END; + + /** SQL query that accesses the planetary resources dump view */ + private static final String Q_PLANET_RESOURCES = SQL_START + "planet_resources" + SQL_END; + + /** SQL query that accesses the build queues dump view */ + private static final String Q_BUILD_QUEUES = SQL_START + "queues" + SQL_END + " ORDER BY queue_order"; + + /** SQL query that accesses the buildings dump view */ + private static final String Q_BUILDINGS = SQL_START + "buildings" + SQL_END; + + /** SQL query that accesses the fleets dump view */ + private static final String Q_FLEETS = SQL_START + "fleets" + SQL_END; + + /** SQL query that accesses the ships dump view */ + private static final String Q_SHIPS = SQL_START + "ships" + SQL_END; + /** JDBC access interface */ private JdbcTemplate dTemplate; @@ -55,6 +87,9 @@ public class EmpireSummaryBean /** Empire-owned planet row mapper */ private final PlanetInformationMapper mPlanet; + /** Planet resources row mapper */ + private final ResourceRowMapper mPlanetResources; + /** Planet construction queue item row mapper */ private final QueueItemInformationMapper mQueueItem; @@ -79,12 +114,14 @@ public class EmpireSummaryBean AccountInformation.class , AllianceInformation.class , BuildingsInformation.class , DebugInformation.class , EmpireInformation.class , FleetInformation.class , MovementInformation.class , PlanetInformation.class , QueueInformation.class , QueueItemInformation.class , - ResearchInformation.class , ShipsInformation.class , SystemInformation.class + ResearchInformation.class , ResourceDeltaInformation.class , ResourceProviderInformation.class , + ShipsInformation.class , SystemInformation.class } ); this.mMainInfo = new DebugInformationMapper( ); this.mResearch = new ResearchInformationMapper( ); this.mPlanet = new PlanetInformationMapper( ); + this.mPlanetResources = new ResourceRowMapper( ); this.mQueueItem = new QueueItemInformationMapper( ); this.mBuildings = new BuildingsInformationMapper( ); this.mFleet = new FleetInformationMapper( ); @@ -116,46 +153,174 @@ public class EmpireSummaryBean @Override public String getSummary( int empireId ) { - String sql = "SELECT * FROM bugs.dump_main_view WHERE empire_id = ?"; - DebugInformation di = this.dTemplate.queryForObject( sql , this.mMainInfo , empireId ); + DebugInformation empireDump = this.dTemplate.queryForObject( Q_EMPIRE , this.mMainInfo , empireId ); + this.getResearch( empireId , empireDump ); - sql = "SELECT * FROM bugs.dump_research_view WHERE empire_id = ?"; - for ( ResearchInformation ri : this.dTemplate.query( sql , this.mResearch , empireId ) ) { - di.getResearch( ).add( ri ); + this.getPlanets( empireId , empireDump ); + this.getFleets( empireId , empireDump ); + + return this.xStream.toXML( empireDump ); + } + + + /** + * Get research information + * + *

+ * Read all research-related information from the appropriate dump view, and add corresponding + * entries to the top-level instance. + * + * @param empireId + * the empire's identifier + * @param empireDump + * the top-level instance + */ + private void getResearch( int empireId , DebugInformation empireDump ) + { + for ( ResearchInformation ri : this.dTemplate.query( Q_RESEARCH , this.mResearch , empireId ) ) { + empireDump.getResearch( ).add( ri ); + } + } + + + /** + * Get empire planets and related information + * + *

+ * Read the planet list and basic planet information from the appropriate dump view, then read + * all extra information (resources, build queues, buildings). + * + * @param empireId + * the empire's identifier + * @param empireDump + * the top-level instance + */ + private void getPlanets( int empireId , DebugInformation empireDump ) + { + HashMap< Integer , PlanetInformation > planets = new HashMap< Integer , PlanetInformation >( ); + for ( PlanetInformation planet : this.dTemplate.query( Q_PLANETS , this.mPlanet , empireId ) ) { + empireDump.getPlanets( ).add( planet ); + planets.put( planet.getId( ) , planet ); } - sql = "SELECT * FROM bugs.dump_planets_view WHERE empire_id = ?"; - Map< Integer , PlanetInformation > planets = new HashMap< Integer , PlanetInformation >( ); - for ( PlanetInformation pi : this.dTemplate.query( sql , this.mPlanet , empireId ) ) { - di.getPlanets( ).add( pi ); - planets.put( pi.getId( ) , pi ); - } + this.getPlanetResources( empireId , planets ); + this.getBuildQueues( empireId , planets ); + this.getBuildings( empireId , planets ); + } - sql = "SELECT * FROM bugs.dump_queues_view WHERE empire_id = ? ORDER BY queue_order"; - for ( QueueItemInformation qii : this.dTemplate.query( sql , this.mQueueItem , empireId ) ) { - PlanetInformation pi = planets.get( qii.getPlanetId( ) ); - QueueInformation qi = ( qii.isMilitary( ) ? pi.getMilitaryQueue( ) : pi.getCivilianQueue( ) ); - qi.getItems( ).add( qii ); - } - sql = "SELECT * FROM bugs.dump_buildings_view WHERE empire_id = ?"; - for ( BuildingsInformation bi : this.dTemplate.query( sql , this.mBuildings , empireId ) ) { + /** + * Add resources information to planets + * + *

+ * Access resources information for the empire's planets and add the records to each planet. + * + * @param empireId + * the empire's identifier + * @param planets + * a map associating planet records with their identifier + */ + private void getPlanetResources( int empireId , Map< Integer , PlanetInformation > planets ) + { + for ( PlanetResourceRow resRow : this.dTemplate.query( Q_PLANET_RESOURCES , this.mPlanetResources , empireId ) ) { + PlanetInformation planet = planets.get( resRow.getPlanetId( ) ); + planet.getResourceDeltas( ).add( resRow.getDelta( ) ); + + ResourceProviderInformation resProv = resRow.getProvider( ); + if ( resProv != null ) { + planet.getResourceProviders( ).add( resProv ); + } + } + } + + + /** + * Add build queue information to planet records + * + *

+ * Access the contents of build queues and add the records to the corresponding planets. + * + * @param empireId + * the empire's identifier + * @param planets + * the map of planets by identifier + */ + private void getBuildQueues( int empireId , Map< Integer , PlanetInformation > planets ) + { + for ( QueueItemInformation queueItem : this.dTemplate.query( Q_BUILD_QUEUES , this.mQueueItem , empireId ) ) { + PlanetInformation planet = planets.get( queueItem.getPlanetId( ) ); + + QueueInformation queue; + if ( queueItem.isMilitary( ) ) { + queue = planet.getMilitaryQueue( ); + } else { + queue = planet.getCivilianQueue( ); + } + + queue.getItems( ).add( queueItem ); + } + } + + + /** + * Add buildings information to planet records + * + *

+ * Access the contents of the buildings dump view and add the building records to the + * corresponding planets. + * + * @param empireId + * the empire's identifier + * @param planets + * the map of planets by identifier + */ + private void getBuildings( int empireId , Map< Integer , PlanetInformation > planets ) + { + for ( BuildingsInformation bi : this.dTemplate.query( Q_BUILDINGS , this.mBuildings , empireId ) ) { planets.get( bi.getPlanetId( ) ).getBuildings( ).add( bi ); } + } - sql = "SELECT * FROM bugs.dump_fleets_view WHERE empire_id = ?"; + + /** + * Retrieve information about the empire's fleets + * + *

+ * Access the list of fleets, add the records to the top-level instance, then retrieve all + * necessary information. + * + * @param empireId + * the empire's identifier + * @param empireDump + * the top-level empire dump + */ + private void getFleets( int empireId , DebugInformation empireDump ) + { Map< Long , FleetInformation > fleets = new HashMap< Long , FleetInformation >( ); - for ( FleetInformation fi : this.dTemplate.query( sql , this.mFleet , empireId ) ) { - di.getFleets( ).add( fi ); + for ( FleetInformation fi : this.dTemplate.query( Q_FLEETS , this.mFleet , empireId ) ) { + empireDump.getFleets( ).add( fi ); fleets.put( fi.getId( ) , fi ); } + this.getShips( empireId , fleets ); + } - sql = "SELECT * FROM bugs.dump_ships_view WHERE empire_id = ?"; - for ( ShipsInformation si : this.dTemplate.query( sql , this.mShips , empireId ) ) { + + /** + * Add ships information to fleet records + * + *

+ * Retrieve information about ships and add the records to the corresponding fleets. + * + * @param empireId + * the empire's identifier + * @param fleets + * the map of fleets by identifier + */ + private void getShips( int empireId , Map< Long , FleetInformation > fleets ) + { + for ( ShipsInformation si : this.dTemplate.query( Q_SHIPS , this.mShips , empireId ) ) { fleets.get( si.getFleetId( ) ).getShips( ).add( si ); } - - return this.xStream.toXML( di ); } } diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetResourceRow.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetResourceRow.java new file mode 100644 index 0000000..3d6a7e2 --- /dev/null +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetResourceRow.java @@ -0,0 +1,96 @@ +package com.deepclone.lw.beans.bt.es; + + +import com.deepclone.lw.beans.bt.es.data.ResourceDeltaInformation; +import com.deepclone.lw.beans.bt.es.data.ResourceProviderInformation; + + + +/** + * Planet resource row information + * + *

+ * Planet resources and resource providers are both extracted from the same + * bugs.planet_resources_view rows. Because of that, this class is used to transmit the + * information (as a {@link ResourceDeltaInformation} instance and an optional + * {@link ResourceProviderInformation} instance) from the row mapper to the summary creation + * component. + * + * @author E. Benoît + */ +class PlanetResourceRow +{ + + /** Identifier of the planet */ + private final int planetId; + + /** Resource delta information */ + private final ResourceDeltaInformation delta = new ResourceDeltaInformation( ); + + /** Resource provider information */ + private ResourceProviderInformation provider; + + + /** + * Initialise the instance by setting the planet identifier + * + * @param planetId + * the planet's identifier + */ + public PlanetResourceRow( int planetId ) + { + this.planetId = planetId; + } + + + /** @return the planet's identifier */ + public int getPlanetId( ) + { + return this.planetId; + } + + + /** @return the resource delta information record */ + public ResourceDeltaInformation getDelta( ) + { + return this.delta; + } + + + /** @return the resource provider information record */ + public ResourceProviderInformation getProvider( ) + { + return this.provider; + } + + + /** + * Set the resource provider information record + * + * @param provider + * the resource provider information record + */ + public void setProvider( ResourceProviderInformation provider ) + { + this.provider = provider; + } + + + /** + * Set the name of the resource + * + *

+ * This method should be called once the rest of the record(s) has been initialised. It will set + * the resource name on both the delta and the provider (if the latter exists). + * + * @param resource + * the name of the resource + */ + public void setResource( String resource ) + { + this.delta.setResource( resource ); + if ( this.provider != null ) { + this.provider.setResource( resource ); + } + } +} diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResourceRowMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResourceRowMapper.java new file mode 100644 index 0000000..5925cfd --- /dev/null +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResourceRowMapper.java @@ -0,0 +1,58 @@ +package com.deepclone.lw.beans.bt.es; + + +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.jdbc.core.RowMapper; + +import com.deepclone.lw.beans.bt.es.data.ResourceProviderInformation; + + + +/** + * Mapper which extract planet resources and resource providers information + * + *

+ * This class maps rows from bugs.dump_planet_resources_view into + * {@link PlanetResourceRow} instances. + * + * @author E. Benoît + * + */ +class ResourceRowMapper + implements RowMapper< PlanetResourceRow > +{ + + /** + * Map a row from bugs.dump_planet_resources_view + * + *

+ * Generate the {@link PlanetResourceRow} instance with the correct planet identifier, resource + * name, income and upkeep. If there is also a resource provider, attach a + * {@link ResourceProviderInformation} instance to the result. + */ + @Override + public PlanetResourceRow mapRow( ResultSet rs , int rowNum ) + throws SQLException + { + PlanetResourceRow row = new PlanetResourceRow( rs.getInt( "planet_id" ) ); + + row.getDelta( ).setIncome( rs.getDouble( "pres_income" ) ); + row.getDelta( ).setUpkeep( rs.getDouble( "pres_upkeep" ) ); + + double pCapacity = rs.getDouble( "resprov_quantity_max" ); + if ( !rs.wasNull( ) ) { + ResourceProviderInformation rpi = new ResourceProviderInformation( ); + rpi.setMaximalQuantity( pCapacity ); + rpi.setCurrentQuantity( rs.getDouble( "resprov_quantity" ) ); + rpi.setDifficulty( rs.getDouble( "resprov_difficulty" ) ); + rpi.setRecovery( rs.getDouble( "resprov_recovery" ) ); + row.setProvider( rpi ); + } + + row.setResource( rs.getString( "resource_name" ) ); + return row; + } + +} diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/DebugInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/DebugInformation.java index 76074b8..2959182 100644 --- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/DebugInformation.java +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/DebugInformation.java @@ -19,7 +19,7 @@ public class DebugInformation @XStreamAsAttribute @XStreamAlias( "dump-version" ) - private int version = 1; + private int version = 2; private SystemInformation system = new SystemInformation( ); diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/InvalidDumpContentsException.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/InvalidDumpContentsException.java new file mode 100644 index 0000000..2044984 --- /dev/null +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/InvalidDumpContentsException.java @@ -0,0 +1,60 @@ +package com.deepclone.lw.beans.bt.es.data; + + +import java.io.Serializable; + + + +/** + * Invalid dump contents exception + * + *

+ * This runtime exception is thrown by the debugging data record classes when one of the fields is + * set to an incorrect value. + * + * @author E. Benoît + * + */ +public final class InvalidDumpContentsException + extends RuntimeException +{ + /** Serialisation identifier */ + private static final long serialVersionUID = 1L; + + /** Class in which the error was caused */ + private final Class< ? extends Serializable > recordType; + + /** Name of the field to which invalid contents were assigned */ + private final String field; + + + /** + * Initialise the exception by setting the record and field + * + * @param type + * the type of the XML dump record + * @param field + * the field to which invalid contents were assigned + */ + InvalidDumpContentsException( Class< ? extends Serializable > type , String field ) + { + super( "Invalid contents for field " + field + " of record " + type.getSimpleName( ) ); + this.recordType = type; + this.field = field; + } + + + /** @return the type of the XML dump record */ + public Class< ? extends Serializable > getRecordType( ) + { + return this.recordType; + } + + + /** @return the field to which invalid contents were assigned */ + public String getField( ) + { + return this.field; + } + +} diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/PlanetInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/PlanetInformation.java index de9c6b6..bd60545 100644 --- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/PlanetInformation.java +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/PlanetInformation.java @@ -7,118 +7,204 @@ import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; +import com.thoughtworks.xstream.annotations.XStreamImplicit; +/** + * Planet XML record + * + *

+ * This class is used in XML dumps to represent the information about a planet. It includes a few + * basic values, as well as information about buildings, queues and resources. + * + *

+ * This record exists since version 1 (B6M1) of XML dumps. However, the following changes were made + * later. + *

+ * + * @author E. Benoît + * + */ @XStreamAlias( "planet" ) +@SuppressWarnings( "serial" ) public class PlanetInformation implements Serializable { - private static final long serialVersionUID = 1L; - + /** Planet identifier */ @XStreamAsAttribute - @XStreamAlias( "id" ) - private int id; + private Integer id; + /** Planet name */ @XStreamAsAttribute - @XStreamAlias( "id" ) private String name; + /** Current population of the planet */ @XStreamAlias( "population" ) - private double population; + private Double population; + /** Current happiness of the planet's population */ @XStreamAlias( "current-happiness" ) - private double currentHappiness; + private Double currentHappiness; + /** Target happiness of the planet's population */ @XStreamAlias( "target-happiness" ) private double targetHappiness; + /** List of buildings */ @XStreamAlias( "buildings" ) - private List< BuildingsInformation > buildings = new LinkedList< BuildingsInformation >( ); + private final List< BuildingsInformation > buildings = new LinkedList< BuildingsInformation >( ); + /** Civilian construction queue */ @XStreamAlias( "civ-queue" ) - private QueueInformation civilianQueue = new QueueInformation( ); + private final QueueInformation civilianQueue = new QueueInformation( ); + /** Military construction queue */ @XStreamAlias( "mil-queue" ) - private QueueInformation militaryQueue = new QueueInformation( ); + private final QueueInformation militaryQueue = new QueueInformation( ); + + /** Planet resource deltas */ + @XStreamImplicit + private final LinkedList< ResourceDeltaInformation > resourceDeltas = new LinkedList< ResourceDeltaInformation >( ); + + /** List of resource providers */ + @XStreamImplicit( itemFieldName = "resource-provider" ) + private final LinkedList< ResourceProviderInformation > resourceProviders = new LinkedList< ResourceProviderInformation >( ); - public int getId( ) + /** @return the planet's identifier */ + public Integer getId( ) { - return id; + return this.id; } + /** + * Set the planet's identifier + * + * @param id + * the planet's identifier + */ public void setId( int id ) { this.id = id; } + /** @return the planet's name */ public String getName( ) { - return name; + return this.name; } + /** + * Set the planet's name + * + * @param name + * the planet's name + */ public void setName( String name ) { this.name = name; } - public double getPopulation( ) + /** @return the planet's current population */ + public Double getPopulation( ) { - return population; + return this.population; } + /** + * Set the planet's current population + * + * @param population + * the planet's current population + */ public void setPopulation( double population ) { this.population = population; } - public double getCurrentHappiness( ) + /** @return the current happiness of the planet's population */ + public Double getCurrentHappiness( ) { - return currentHappiness; + return this.currentHappiness; } + /** + * Set the current happiness of the planet's population + * + * @param currentHappiness + * the current happiness of the planet's population + */ public void setCurrentHappiness( double currentHappiness ) { this.currentHappiness = currentHappiness; } - public double getTargetHappiness( ) + /** @return the target happiness of the planet's population */ + public Double getTargetHappiness( ) { - return targetHappiness; + return this.targetHappiness; } + /** + * Set the target happiness of the planet's population + * + * @param targetHappiness + * the target happiness of the planet's population + */ public void setTargetHappiness( double targetHappiness ) { this.targetHappiness = targetHappiness; } + /** @return the list of buildings constructed on the planet */ public List< BuildingsInformation > getBuildings( ) { - return buildings; + return this.buildings; } + /** @return the civilian construction queue */ public QueueInformation getCivilianQueue( ) { - return civilianQueue; + return this.civilianQueue; } + /** @return the military construction queue */ public QueueInformation getMilitaryQueue( ) { - return militaryQueue; + return this.militaryQueue; + } + + + /** @return the list of resource delta records */ + public LinkedList< ResourceDeltaInformation > getResourceDeltas( ) + { + return this.resourceDeltas; + } + + + /** @return the list of resource provider records */ + public LinkedList< ResourceProviderInformation > getResourceProviders( ) + { + return this.resourceProviders; } } diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceDeltaInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceDeltaInformation.java new file mode 100644 index 0000000..679b077 --- /dev/null +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceDeltaInformation.java @@ -0,0 +1,109 @@ +package com.deepclone.lw.beans.bt.es.data; + + +import java.io.Serializable; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamAsAttribute; + + + +/** + * Resource delta information + * + *

+ * This class represents records which contain a resource's delta - that is, the income and upkeep + * for some type of resource. + * + * @author E. Benoît + */ +@SuppressWarnings( "serial" ) +@XStreamAlias( "resource-delta" ) +public class ResourceDeltaInformation + implements Serializable +{ + + /** Identifier of the resource */ + @XStreamAlias( "id" ) + @XStreamAsAttribute + private String resource; + + /** Income for that type of resource */ + @XStreamAsAttribute + private Double income; + + /** Upkeep for that type of resource */ + @XStreamAsAttribute + private Double upkeep; + + + /** @return the resource's identifier */ + public String getResource( ) + { + return this.resource; + } + + + /** + * Set the resource's identifier + * + * @param resource + * the resource's identifier + * + * @throws InvalidDumpContentsException + * if the specified resource type is null + */ + public void setResource( String resource ) + throws InvalidDumpContentsException + { + if ( resource == null ) { + throw new InvalidDumpContentsException( this.getClass( ) , "resource" ); + } + this.resource = resource; + } + + + /** + * @return the income for that type of resource, or null if no income information + * is available + */ + public Double getIncome( ) + { + return this.income; + } + + + /** + * Set the income for that type of resource + * + * @param income + * the income for that type of resource + */ + public void setIncome( double income ) + { + this.income = income; + } + + + /** + * @return the upkeep for that type of resource, or null if no upkeep information + * is available + */ + public Double getUpkeep( ) + { + return this.upkeep; + } + + + /** + * Set the upkeep for that type of resource + * + * @param upkeep + * the upkeep for that type of resource + */ + public void setUpkeep( double upkeep ) + { + this.upkeep = upkeep; + } + +} diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceProviderInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceProviderInformation.java new file mode 100644 index 0000000..c29054c --- /dev/null +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceProviderInformation.java @@ -0,0 +1,152 @@ +package com.deepclone.lw.beans.bt.es.data; + + +import java.io.Serializable; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamAsAttribute; + + + +/** + * Resource provider XML record + * + *

+ * This class represents the information about a resource provider that will be serialised to the + * debugging XML dump when a player posts a bug report. + * + *

+ * This record exists since version 2 (B6M2) of XML dumps. + * + * @author E. Benoît + */ +@SuppressWarnings( "serial" ) +public class ResourceProviderInformation + implements Serializable +{ + + /** Identifier of the resource */ + @XStreamAsAttribute + private String resource; + + /** Maximal quantity in the provider */ + @XStreamAsAttribute + @XStreamAlias( "max" ) + private Double maximalQuantity; + + /** Current quantity in the provider */ + @XStreamAsAttribute + @XStreamAlias( "current" ) + private Double currentQuantity; + + /** Extraction difficulty */ + @XStreamAsAttribute + private Double difficulty; + + /** Recovery rate */ + @XStreamAsAttribute + private Double recovery; + + + /** @return the resource's identifier */ + public String getResource( ) + { + return this.resource; + } + + + /** + * Set the resource's identifier + * + * @param resource + * the resource's identifier + * + * @throws InvalidDumpContentsException + * if the resource's identifier is null + */ + public void setResource( String resource ) + throws InvalidDumpContentsException + { + if ( resource == null ) { + throw new InvalidDumpContentsException( this.getClass( ) , "resource" ); + } + this.resource = resource; + } + + + /** @return the provider's total capacity */ + public Double getMaximalQuantity( ) + { + return this.maximalQuantity; + } + + + /** + * Set the maximal quantity of resources in the provider + * + * @param maximalQuantity + * the provider's total capacity + */ + public void setMaximalQuantity( double maximalQuantity ) + { + this.maximalQuantity = maximalQuantity; + } + + + /** @return the current quantity of resources in the provider */ + public Double getCurrentQuantity( ) + { + return this.currentQuantity; + } + + + /** + * Set the current quantity of resources in the provider + * + * @param currentQuantity + * the current quantity of resources in the provider + */ + public void setCurrentQuantity( double currentQuantity ) + { + this.currentQuantity = currentQuantity; + } + + + /** @return the provider's extraction difficulty */ + public Double getDifficulty( ) + { + return this.difficulty; + } + + + /** + * Set the provider's extraction difficulty + * + * @param difficulty + * the provider's extraction difficulty + */ + public void setDifficulty( double difficulty ) + { + this.difficulty = difficulty; + } + + + /** @return the provider's recovery rate */ + public Double getRecovery( ) + { + return this.recovery; + } + + + /** + * Set the provider's recovery rate + * + * @param recovery + * the provider's recovery rate + */ + public void setRecovery( double recovery ) + { + this.recovery = recovery; + } + +} diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/200-bugs.sql b/legacyworlds-server-data/db-structure/parts/040-functions/200-bugs.sql index f8d7282..1d9a23d 100644 --- a/legacyworlds-server-data/db-structure/parts/040-functions/200-bugs.sql +++ b/legacyworlds-server-data/db-structure/parts/040-functions/200-bugs.sql @@ -1220,6 +1220,54 @@ CREATE VIEW bugs.dump_planets_view GRANT SELECT ON bugs.dump_planets_view TO :dbuser; + +/* + * Planet resources view for XML dumps + * ------------------------------------ + * + * This view combines both planet resources and resource providers for all + * empire-owned planets. It is meant to be used in the XML dump generator. + * + * + * Columns: + * empire_id The empire's identifier + * planet_id The planet's identifier + * resource_name The string identifying the resource + * pres_income The planet's income for that resource type + * pres_upkeep The planet's upkeep for that resource type + * resprov_quantity_max The resource provider's capacity, or NULL + * if there is no resource provider of that + * type on the planet + * resprov_quantity The resource provider's current quantity, or + * NULL if there is no resource provider of + * that type on the planet + * resprov_difficulty The resource provider's extraction difficulty, + * or NULL if there is no resource provider + * of that type on the planet + * resprov_recovery The resource provider's recovery rate, or NULL + * if there is no resource provider of that + * type on the planet + */ +CREATE VIEW bugs.dump_planet_resources_view + AS SELECT empire_id , planet_id , + name AS resource_name , + pres_income , pres_upkeep , + resprov_quantity_max , resprov_quantity , + resprov_difficulty , resprov_recovery + FROM emp.planets + INNER JOIN verse.planet_resources + USING ( planet_id ) + INNER JOIN defs.strings + ON resource_name_id = id + LEFT OUTER JOIN verse.resource_providers + USING ( planet_id , resource_name_id ) + ORDER BY name; + +GRANT SELECT + ON bugs.dump_planet_resources_view + TO :dbuser; + + CREATE VIEW bugs.dump_queues_view AS SELECT ep.empire_id , ep.planet_id , FALSE AS military , q.queue_order , q.building_id AS item_id , qin.name AS item_name , diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/010-dump-planet-resources-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/010-dump-planet-resources-view.sql new file mode 100644 index 0000000..23c8aa5 --- /dev/null +++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/010-dump-planet-resources-view.sql @@ -0,0 +1,73 @@ +/* + * Tests for bugs.dump_planet_resources_view + */ +BEGIN; + /* + * We need a couple of resources (one natural, one basic), three planets + * with valid planet resource records (two of the planets will have a + * resource provider), two empires (owning a planet with and without + * resource providers, respectively). + */ + \i utils/strings.sql + \i utils/resources.sql + \i utils/accounts.sql + \i utils/naming.sql + \i utils/universe.sql + SELECT _create_natural_resources( 1 , 'natRes' ); + SELECT _create_resources( 1 , 'basicRes' ); + SELECT _create_raw_planets( 3 , 'planet' ); + INSERT INTO verse.planet_resources( + planet_id , resource_name_id , pres_income , pres_upkeep + ) VALUES ( + _get_map_name( 'planet1' ) , _get_string( 'basicRes1' ) , 1 , 2 + ) , ( + _get_map_name( 'planet1' ) , _get_string( 'natRes1' ) , 3 , 4 + ) , ( + _get_map_name( 'planet2' ) , _get_string( 'basicRes1' ) , 5 , 6 + ) , ( + _get_map_name( 'planet2' ) , _get_string( 'natRes1' ) , 7 , 8 + ) , ( + _get_map_name( 'planet3' ) , _get_string( 'basicRes1' ) , 9 , 10 + ) , ( + _get_map_name( 'planet3' ) , _get_string( 'natRes1' ) , 11 , 12 + ); + SELECT _create_resource_provider( 'planet1' , 'natRes1' ); + SELECT _create_resource_provider( 'planet3' , 'natRes1' ); + + SELECT _create_emp_names( 2 , 'empire' ); + SELECT emp.create_empire( _get_emp_name( 'empire1' ) , + _get_map_name( 'planet1' ) , + 200.0 ); + SELECT emp.create_empire( _get_emp_name( 'empire2' ) , + _get_map_name( 'planet2' ) , + 200.0 ); + + + + /***** TESTS BEGIN HERE *****/ + SELECT plan( 2 ); + + SELECT diag_test_name( 'bugs.dump_planet_resources_view - Records without resource providers' ); + SELECT set_eq( $$ + SELECT empire_id , planet_id , resource_name , pres_income , pres_upkeep + FROM bugs.dump_planet_resources_view + WHERE resprov_quantity IS NULL + $$ , $$ VALUES ( + _get_emp_name( 'empire1' ) , _get_map_name( 'planet1' ) , 'basicRes1' , 1 , 2 + ) , ( + _get_emp_name( 'empire2' ) , _get_map_name( 'planet2' ) , 'basicRes1' , 5 , 6 + ) , ( + _get_emp_name( 'empire2' ) , _get_map_name( 'planet2' ) , 'natRes1' , 7 , 8 + ) $$ ); + + SELECT diag_test_name( 'bugs.dump_planet_resources_view - Records with resource providers' ); + SELECT set_eq( $$ + SELECT empire_id , planet_id , resource_name , pres_income , pres_upkeep + FROM bugs.dump_planet_resources_view + WHERE resprov_quantity IS NOT NULL + $$ , $$ VALUES ( + _get_emp_name( 'empire1' ) , _get_map_name( 'planet1' ) , 'natRes1' , 3 , 4 + ) $$ ); + + SELECT * FROM finish( ); +ROLLBACK; \ No newline at end of file diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/010-dump-planet-resources-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/010-dump-planet-resources-view.sql new file mode 100644 index 0000000..5100491 --- /dev/null +++ b/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/010-dump-planet-resources-view.sql @@ -0,0 +1,11 @@ +/* + * Test privileges on bugs.dump_planet_resources_view + */ +BEGIN; + SELECT plan( 1 ); + + SELECT diag_test_name( 'bugs.dump_planet_resources_view - Privileges' ); + SELECT lives_ok( 'SELECT * FROM bugs.dump_planet_resources_view' ); + + SELECT * FROM finish( ); +ROLLBACK; \ No newline at end of file diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestBuildingsInformationMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestBuildingsInformationMapper.java index c32bf40..cb5209a 100644 --- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestBuildingsInformationMapper.java +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestBuildingsInformationMapper.java @@ -16,6 +16,8 @@ import com.deepclone.lw.testing.MockResultSet; /** * Tests for the {@link BuildingsInformationMapper} class. + * + * @author E. Benoît */ public class TestBuildingsInformationMapper { diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestPlanetResourceRow.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestPlanetResourceRow.java new file mode 100644 index 0000000..f02a3a9 --- /dev/null +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestPlanetResourceRow.java @@ -0,0 +1,102 @@ +package com.deepclone.lw.beans.bt.es; + + +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; + +import com.deepclone.lw.beans.bt.es.data.ResourceProviderInformation; + + + +/** + * Tests for the {@link PlanetResourceRow} class + * + * @author E. Benoît + */ +public class TestPlanetResourceRow +{ + + /** Identifier of the planet in the test object */ + private static final int TEST_IDENTIFIER = 42; + + /** Resource name used in the tests */ + private static final String TEST_NAME = "Test"; + + /** The planet resource row instance used in tests */ + private PlanetResourceRow prr; + + + /** + * Create a planet resource row instance with the planet identifier specified by + * {@link #TEST_IDENTIFIER}. + */ + @Before + public void setUp( ) + { + this.prr = new PlanetResourceRow( TEST_IDENTIFIER ); + } + + + /** + * Planet identifier has been initialised correctly. + */ + @Test + public void testPlanetIdentifier( ) + { + assertEquals( TEST_IDENTIFIER , this.prr.getPlanetId( ) ); + } + + + /** + * By default, the resource delta exists, the provider doesn't. + */ + @Test + public void testDefaultValues( ) + { + assertNotNull( this.prr.getDelta( ) ); + assertNull( this.prr.getProvider( ) ); + } + + + /** + * Setting and reading the resource provider record. + */ + @Test + public void testSetProvider( ) + { + ResourceProviderInformation rpi = new ResourceProviderInformation( ); + rpi.setResource( TEST_NAME ); + this.prr.setProvider( rpi ); + assertNotNull( this.prr.getProvider( ) ); + assertEquals( TEST_NAME , this.prr.getProvider( ).getResource( ) ); + } + + + /** + * Setting the resource name when there is no resource provider record. + */ + @Test + public void testSetNameDeltaOnly( ) + { + this.prr.setResource( TEST_NAME ); + assertEquals( TEST_NAME , this.prr.getDelta( ).getResource( ) ); + assertNull( this.prr.getProvider( ) ); + } + + + /** + * Setting the resource name when there are both a resource delta record and a resource provider + * record. + */ + @Test + public void testSetNameFull( ) + { + this.prr.setProvider( new ResourceProviderInformation( ) ); + this.prr.setResource( TEST_NAME ); + assertEquals( TEST_NAME , this.prr.getDelta( ).getResource( ) ); + assertNotNull( this.prr.getProvider( ) ); + assertEquals( TEST_NAME , this.prr.getProvider( ).getResource( ) ); + } + +} diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestResourceRowMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestResourceRowMapper.java new file mode 100644 index 0000000..2235fbd --- /dev/null +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestResourceRowMapper.java @@ -0,0 +1,129 @@ +package com.deepclone.lw.beans.bt.es; + + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; + +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; + +import com.deepclone.lw.testing.MockResultSet; + + + +/** + * Tests for the {@link ResourceRowMapper} class. + * + * @author E. Benoît + */ +public class TestResourceRowMapper +{ + /** Planet identifiers found in the "results" */ + private static final int[] PLANET_IDS = new int[] { + 1 , 2 + }; + + /** Resource names found in the two "results", respectively */ + private static final String[] RESOURCE_NAMES = new String[] { + "Test1" , "Test2" + }; + + /** Income values found in the two results */ + private static final double[] INCOME_VALUES = new double[] { + 3.0 , 4.0 + }; + + /** Upkeep values found in the two results */ + private static final double[] UPKEEP_VALUES = new double[] { + 5.0 , 6.0 + }; + + /** Resource provider quantity for the second row */ + private static final double RP_QUANTITY = 7.0; + + /** Resource provider capacity for the second row */ + private static final double RP_CAPACITY = 8.0; + + /** Resource provider extraction difficulty for the second row */ + private static final double RP_DIFFICULTY = 9.0; + + /** Resource provider recovery rate for the second row */ + private static final double RP_RECOVERY = 10.0; + + /** The fake result set used in the tests */ + private ResultSet resultSet; + + /** The mapper used in the tests */ + private ResourceRowMapper mapper; + + + /** Create the mapper and the contents of the fake result set */ + @Before + public void setUp( ) + { + this.mapper = new ResourceRowMapper( ); + + @SuppressWarnings( "unchecked" ) + HashMap< String , Object > rows[] = new HashMap[ 2 ]; + for ( int i = 0 ; i < 2 ; i++ ) { + HashMap< String , Object > row = new HashMap< String , Object >( ); + row.put( "planet_id" , PLANET_IDS[ i ] ); + row.put( "resource_name" , RESOURCE_NAMES[ i ] ); + row.put( "pres_income" , INCOME_VALUES[ i ] ); + row.put( "pres_upkeep" , UPKEEP_VALUES[ i ] ); + if ( i == 1 ) { + row.put( "resprov_quantity_max" , RP_CAPACITY ); + row.put( "resprov_quantity" , RP_QUANTITY ); + row.put( "resprov_difficulty" , RP_DIFFICULTY ); + row.put( "resprov_recovery" , RP_RECOVERY ); + } + rows[ i ] = row; + } + + this.resultSet = MockResultSet.create( rows ); + } + + + /** + * Mapping a row with no provider information + */ + @Test + public void testMapNoProvider( ) + throws SQLException + { + this.resultSet.absolute( 1 ); + + PlanetResourceRow row = this.mapper.mapRow( this.resultSet , 0 ); + assertNotNull( row ); + assertEquals( PLANET_IDS[ 0 ] , row.getPlanetId( ) ); + assertEquals( RESOURCE_NAMES[ 0 ] , row.getDelta( ).getResource( ) ); + assertEquals( INCOME_VALUES[ 0 ] , row.getDelta( ).getIncome( ) , 0 ); + assertEquals( UPKEEP_VALUES[ 0 ] , row.getDelta( ).getUpkeep( ) , 0 ); + assertNull( row.getProvider( ) ); + } + + + /** + * Mapping a row with a provider information record + */ + @Test + public void testMapWithProvider( ) + throws SQLException + { + this.resultSet.absolute( 2 ); + + PlanetResourceRow row = this.mapper.mapRow( this.resultSet , 0 ); + assertNotNull( row ); + assertEquals( PLANET_IDS[ 1 ] , row.getPlanetId( ) ); + assertEquals( RESOURCE_NAMES[ 1 ] , row.getDelta( ).getResource( ) ); + assertEquals( INCOME_VALUES[ 1 ] , row.getDelta( ).getIncome( ) , 0 ); + assertEquals( UPKEEP_VALUES[ 1 ] , row.getDelta( ).getUpkeep( ) , 0 ); + assertNotNull( row.getProvider( ) ); + assertEquals( RP_CAPACITY , row.getProvider( ).getMaximalQuantity( ) , 0 ); + assertEquals( RP_QUANTITY , row.getProvider( ).getCurrentQuantity( ) , 0 ); + assertEquals( RP_DIFFICULTY , row.getProvider( ).getDifficulty( ) , 0 ); + assertEquals( RP_RECOVERY , row.getProvider( ).getRecovery( ) , 0 ); + } +} diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestInvalidDumpContentsException.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestInvalidDumpContentsException.java new file mode 100644 index 0000000..a88992d --- /dev/null +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestInvalidDumpContentsException.java @@ -0,0 +1,85 @@ +package com.deepclone.lw.beans.bt.es.data; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; + +import org.junit.Before; +import org.junit.Test; + +import com.deepclone.lw.beans.bt.es.data.InvalidDumpContentsException; + + + +/** + * Tests for the {@link InvalidDumpContentsException} class + * + * @author E. Benoît + */ +public class TestInvalidDumpContentsException +{ + + /** + * A dummy class used to test the {@link InvalidDumpContentsException} class. + * + * @author E. Benoît + */ + @SuppressWarnings( "serial" ) + private static final class TestRecord + implements Serializable + { + // EMPTY + } + + /** Test string used as the "field" parameter */ + private static final String TEST_STRING = "Test"; + + /** Exception instance used to run tests */ + private InvalidDumpContentsException exception; + + + /** + * Set up the test by creating an exception instance using {@link TestRecord} as the target + * class and {@link #TEST_STRING} as the field name. + */ + @Before + public void setUp( ) + { + this.exception = new InvalidDumpContentsException( TestRecord.class , TEST_STRING ); + } + + + /** + * The constructor must set the record's class and field name. + */ + @Test + public void testExceptionData( ) + { + assertEquals( TestRecord.class , this.exception.getRecordType( ) ); + assertEquals( TEST_STRING , this.exception.getField( ) ); + assertNotNull( this.exception.getMessage( ) ); + } + + + /** + * The exception's message must end with the name of the class. + */ + @Test + public void testClassNameInMessage( ) + { + assertTrue( this.exception.getMessage( ).endsWith( " " + TestRecord.class.getSimpleName( ) ) ); + } + + + /** + * The exception's message must contain the name of the field. + */ + @Test + public void testFieldNameInMessage( ) + { + assertTrue( this.exception.getMessage( ).contains( " " + TEST_STRING + " " ) ); + } +} diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceDeltaInformation.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceDeltaInformation.java new file mode 100644 index 0000000..2d899f6 --- /dev/null +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceDeltaInformation.java @@ -0,0 +1,174 @@ +package com.deepclone.lw.beans.bt.es.data; + + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +import com.thoughtworks.xstream.XStream; + + + +/** + * Tests for the {@link ResourceDeltaInformation} XML dump storage class + * + * @author E. Benoît + */ +public class TestResourceDeltaInformation +{ + + /** A string used in tests */ + private static final String TEST_STRING = "This is a test"; + + /** A real number used in tests */ + private static final Double TEST_DOUBLE = 4.2; + + /** A record used in the tests */ + private ResourceDeltaInformation rdi; + + + /** + * Set up the test by creating a new resource delta information record. + */ + @Before + public void setUp( ) + { + this.rdi = new ResourceDeltaInformation( ); + } + + + /** + * All fields are set to null by default + */ + @Test + public void testDefaultValues( ) + { + assertNull( this.rdi.getResource( ) ); + assertNull( this.rdi.getIncome( ) ); + assertNull( this.rdi.getUpkeep( ) ); + } + + + /** + * Setting and reading the resource's name + */ + @Test + public void testResourceName( ) + { + this.rdi.setResource( TEST_STRING ); + assertEquals( TEST_STRING , this.rdi.getResource( ) ); + } + + + /** + * Setting the resource name to null throws {@link InvalidDumpContentsException} + */ + @Test + public void testNullResourceName( ) + { + try { + this.rdi.setResource( null ); + fail( "No InvalidDumpContentsException thrown" ); + } catch ( InvalidDumpContentsException exception ) { + assertEquals( ResourceDeltaInformation.class , exception.getRecordType( ) ); + assertEquals( "resource" , exception.getField( ) ); + } + } + + + /** + * Setting and reading the income + */ + @Test + public void testIncome( ) + { + this.rdi.setIncome( TEST_DOUBLE ); + assertEquals( TEST_DOUBLE , this.rdi.getIncome( ) ); + } + + + /** + * Setting and reading the upkeep + */ + @Test + public void testUpkeep( ) + { + this.rdi.setUpkeep( TEST_DOUBLE ); + assertEquals( TEST_DOUBLE , this.rdi.getUpkeep( ) ); + } + + + /** + * Serialising the instance to XML + */ + @Test + public void testXMLSerialisation( ) + { + this.rdi.setResource( TEST_STRING ); + this.rdi.setIncome( 0.1 ); + this.rdi.setUpkeep( 0.2 ); + + XStream xstream = this.createXStreamInstance( ); + String serialised = xstream.toXML( this.rdi ); + assertNotNull( serialised ); + assertTrue( serialised.startsWith( "" ) ); + assertTrue( serialised.contains( " id=\"" + TEST_STRING + "\"" ) ); + assertTrue( serialised.contains( " income=\"0.1\"" ) ); + assertTrue( serialised.contains( " upkeep=\"0.2\"" ) ); + } + + + /** + * Deserialising an instance that contains data + */ + @Test + public void testXMLDeserialisation( ) + { + String xml = ""; + XStream xstream = this.createXStreamInstance( ); + Object deserialised = xstream.fromXML( xml ); + + assertNotNull( deserialised ); + assertEquals( ResourceDeltaInformation.class , deserialised.getClass( ) ); + this.rdi = (ResourceDeltaInformation) deserialised; + + assertEquals( "Test" , this.rdi.getResource( ) ); + assertEquals( (Double) 0.1 , this.rdi.getIncome( ) ); + assertEquals( (Double) 0.2 , this.rdi.getUpkeep( ) ); + } + + + /** + * Deserialising an instance that contains no data + */ + @Test + public void testXMLDeserialisationNoData( ) + { + String xml = ""; + XStream xstream = this.createXStreamInstance( ); + Object deserialised = xstream.fromXML( xml ); + + assertNotNull( deserialised ); + assertEquals( ResourceDeltaInformation.class , deserialised.getClass( ) ); + this.rdi = (ResourceDeltaInformation) deserialised; + + assertNull( this.rdi.getResource( ) ); + assertNull( this.rdi.getIncome( ) ); + assertNull( this.rdi.getUpkeep( ) ); + } + + + /** + * Create and set up the {@link XStream} instance used in the serialisation tests + * + * @return the {@link XStream} instance to use + */ + private XStream createXStreamInstance( ) + { + XStream xstream = new XStream( ); + xstream.processAnnotations( ResourceDeltaInformation.class ); + return xstream; + } +} diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceProviderInformation.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceProviderInformation.java new file mode 100644 index 0000000..d545624 --- /dev/null +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceProviderInformation.java @@ -0,0 +1,207 @@ +package com.deepclone.lw.beans.bt.es.data; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Before; +import org.junit.Test; + +import com.thoughtworks.xstream.XStream; + + + +/** + * Tests for the {@link ResourceProviderInformation} XML dump storage class + * + * @author E. Benoît + */ +public class TestResourceProviderInformation +{ + /** A string used in tests */ + private static final String TEST_STRING = "This is a test"; + + /** A real number used in tests */ + private static final Double TEST_DOUBLE = 4.2; + + /** A resource provider information record */ + private ResourceProviderInformation rpi; + + + @Before + public void setUp( ) + { + this.rpi = new ResourceProviderInformation( ); + } + + + /** + * A new record's fields are all set to null. + */ + @Test + public void testDefaultValues( ) + { + assertNull( this.rpi.getResource( ) ); + assertNull( this.rpi.getCurrentQuantity( ) ); + assertNull( this.rpi.getMaximalQuantity( ) ); + assertNull( this.rpi.getDifficulty( ) ); + assertNull( this.rpi.getRecovery( ) ); + } + + + /** + * Setting and reading the resource's name + */ + @Test + public void testResourceName( ) + { + this.rpi.setResource( TEST_STRING ); + assertEquals( TEST_STRING , this.rpi.getResource( ) ); + } + + + /** + * Setting the resource name to null throws {@link InvalidDumpContentsException} + */ + @Test + public void testNullResourceName( ) + { + try { + this.rpi.setResource( null ); + fail( "No InvalidDumpContentsException thrown" ); + } catch ( InvalidDumpContentsException exception ) { + assertEquals( ResourceProviderInformation.class , exception.getRecordType( ) ); + assertEquals( "resource" , exception.getField( ) ); + } + } + + + /** + * Setting and reading the current quantity + */ + @Test + public void testCurrentQuantity( ) + { + this.rpi.setCurrentQuantity( TEST_DOUBLE ); + assertEquals( TEST_DOUBLE , this.rpi.getCurrentQuantity( ) ); + } + + + /** + * Setting and reading the maximal quantity + */ + @Test + public void testMaximalQuantity( ) + { + this.rpi.setMaximalQuantity( TEST_DOUBLE ); + assertEquals( TEST_DOUBLE , this.rpi.getMaximalQuantity( ) ); + } + + + /** + * Setting and reading the extraction difficulty + */ + @Test + public void testDifficulty( ) + { + this.rpi.setDifficulty( TEST_DOUBLE ); + assertEquals( TEST_DOUBLE , this.rpi.getDifficulty( ) ); + } + + + /** + * Setting and reading the recovery rate + */ + @Test + public void testRecovery( ) + { + this.rpi.setRecovery( TEST_DOUBLE ); + assertEquals( TEST_DOUBLE , this.rpi.getRecovery( ) ); + } + + + /** + * Serialising the instance to XML + */ + @Test + public void testXMLSerialisation( ) + { + this.rpi.setResource( TEST_STRING ); + this.rpi.setCurrentQuantity( 0.1 ); + this.rpi.setMaximalQuantity( 0.2 ); + this.rpi.setDifficulty( 0.3 ); + this.rpi.setRecovery( 0.4 ); + + XStream xstream = this.createXStreamInstance( ); + String serialised = xstream.toXML( this.rpi ); + assertNotNull( serialised ); + assertTrue( serialised.startsWith( "" ) ); + assertTrue( serialised.contains( " resource=\"" + TEST_STRING + "\"" ) ); + assertTrue( serialised.contains( " current=\"0.1\"" ) ); + assertTrue( serialised.contains( " max=\"0.2\"" ) ); + assertTrue( serialised.contains( " difficulty=\"0.3\"" ) ); + assertTrue( serialised.contains( " recovery=\"0.4\"" ) ); + } + + + /** + * Deserialising an instance that contains data + */ + @Test + public void testXMLDeserialisation( ) + { + String xml = ""; + XStream xstream = this.createXStreamInstance( ); + Object deserialised = xstream.fromXML( xml ); + + assertNotNull( deserialised ); + assertEquals( ResourceProviderInformation.class , deserialised.getClass( ) ); + this.rpi = (ResourceProviderInformation) deserialised; + + assertEquals( "Test" , this.rpi.getResource( ) ); + assertEquals( (Double) 0.1 , this.rpi.getCurrentQuantity( ) ); + assertEquals( (Double) 0.2 , this.rpi.getMaximalQuantity( ) ); + assertEquals( (Double) 0.3 , this.rpi.getDifficulty( ) ); + assertEquals( (Double) 0.4 , this.rpi.getRecovery( ) ); + } + + + /** + * Deserialising an instance that contains no data + */ + @Test + public void testXMLDeserialisationNoData( ) + { + String xml = ""; + XStream xstream = this.createXStreamInstance( ); + Object deserialised = xstream.fromXML( xml ); + + assertNotNull( deserialised ); + assertEquals( ResourceProviderInformation.class , deserialised.getClass( ) ); + this.rpi = (ResourceProviderInformation) deserialised; + + assertNull( this.rpi.getResource( ) ); + assertNull( this.rpi.getCurrentQuantity( ) ); + assertNull( this.rpi.getMaximalQuantity( ) ); + assertNull( this.rpi.getDifficulty( ) ); + assertNull( this.rpi.getRecovery( ) ); + } + + + /** + * Create and set up the {@link XStream} instance used in the serialisation tests + * + * @return the {@link XStream} instance to use + */ + private XStream createXStreamInstance( ) + { + XStream xstream = new XStream( ); + xstream.processAnnotations( ResourceProviderInformation.class ); + xstream.alias( "resource-provider" , ResourceProviderInformation.class ); + return xstream; + } +}