From 9b346a80c2b0608bcf826947be89cb0d3f8d2a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Thu, 19 Jan 2012 09:35:12 +0100 Subject: [PATCH] Empire resources in XML dumps * Added dump view for empire resources * Added empire resource information storage class and associated row mapper * Integrated empire resource information into the summary generator --- .../es/EmpireResourceInformationMapper.java | 46 ++++++ .../lw/beans/bt/es/EmpireSummaryBean.java | 31 ++++ .../beans/bt/es/data/EmpireInformation.java | 91 ++++++++++-- .../bt/es/data/EmpireResourceInformation.java | 103 +++++++++++++ .../parts/040-functions/200-bugs.sql | 25 ++++ .../200-bugs/005-dump-emp-resources-view.sql | 36 +++++ .../200-bugs/005-dump-emp-resources-view.sql | 11 ++ .../TestEmpireResourceInformationMapper.java | 74 +++++++++ .../data/TestEmpireResourceInformation.java | 140 ++++++++++++++++++ 9 files changed, 542 insertions(+), 15 deletions(-) create mode 100644 legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireResourceInformationMapper.java create mode 100644 legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireResourceInformation.java create mode 100644 legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/005-dump-emp-resources-view.sql create mode 100644 legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/005-dump-emp-resources-view.sql create mode 100644 legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestEmpireResourceInformationMapper.java create mode 100644 legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestEmpireResourceInformation.java diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireResourceInformationMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireResourceInformationMapper.java new file mode 100644 index 0000000..aefb01d --- /dev/null +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireResourceInformationMapper.java @@ -0,0 +1,46 @@ +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.EmpireResourceInformation; + + + +/** + * Empire resource row mapper + * + *

+ * This class is responsible for transforming rows from bugs.dump_emp_resources_view + * into {@link EmpireResourceInformation} instances. + * + * @author E. Benoît + */ +final class EmpireResourceInformationMapper + implements RowMapper< EmpireResourceInformation > +{ + + /** + * Map a row from bugs.dump_emp_resources_view + * + *

+ * Create a new {@link EmpireResourceInformation} instance and set its fields using the row's + * contents. + */ + @Override + public EmpireResourceInformation mapRow( ResultSet rs , int rowNum ) + throws SQLException + { + EmpireResourceInformation empRes = new EmpireResourceInformation( ); + + empRes.setResource( rs.getString( "resource_name" ) ); + empRes.setOwed( rs.getDouble( "empres_owed" ) ); + empRes.setPossessed( rs.getDouble( "empres_possessed" ) ); + + return empRes; + } + +} 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 bc2fa7d..a6ec5f8 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 @@ -2,6 +2,7 @@ package com.deepclone.lw.beans.bt.es; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.sql.DataSource; @@ -14,6 +15,7 @@ import com.deepclone.lw.beans.bt.es.data.AllianceInformation; import com.deepclone.lw.beans.bt.es.data.BuildingsInformation; import com.deepclone.lw.beans.bt.es.data.DebugInformation; import com.deepclone.lw.beans.bt.es.data.EmpireInformation; +import com.deepclone.lw.beans.bt.es.data.EmpireResourceInformation; import com.deepclone.lw.beans.bt.es.data.FleetInformation; import com.deepclone.lw.beans.bt.es.data.MovementInformation; import com.deepclone.lw.beans.bt.es.data.PlanetInformation; @@ -51,6 +53,9 @@ public class EmpireSummaryBean /** 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 resources dump view */ + private static final String Q_RESOURCES = SQL_START + "emp_resources" + SQL_END; + /** SQL query that accesses the research dump view */ private static final String Q_RESEARCH = SQL_START + "research" + SQL_END; @@ -81,6 +86,9 @@ public class EmpireSummaryBean /** Top-level row mapper */ private final DebugInformationMapper mMainInfo; + /** Empire resources row mapper */ + private final EmpireResourceInformationMapper mResources; + /** Empire research row mapper */ private final ResearchInformationMapper mResearch; @@ -119,6 +127,7 @@ public class EmpireSummaryBean } ); this.mMainInfo = new DebugInformationMapper( ); + this.mResources = new EmpireResourceInformationMapper( ); this.mResearch = new ResearchInformationMapper( ); this.mPlanet = new PlanetInformationMapper( ); this.mPlanetResources = new ResourceRowMapper( ); @@ -154,6 +163,7 @@ public class EmpireSummaryBean public String getSummary( int empireId ) { DebugInformation empireDump = this.dTemplate.queryForObject( Q_EMPIRE , this.mMainInfo , empireId ); + this.getResources( empireId , empireDump ); this.getResearch( empireId , empireDump ); this.getPlanets( empireId , empireDump ); @@ -163,6 +173,27 @@ public class EmpireSummaryBean } + /** + * Extract resources information + * + *

+ * Read the list of empire resources from the appropriate view and add the extracted entries to + * the empire's list of resources. + * + * @param empireId + * the empire's identifier + * @param empireDump + * the top-level instance + */ + private void getResources( int empireId , DebugInformation empireDump ) + { + List< EmpireResourceInformation > resources = empireDump.getEmpire( ).getResources( ); + for ( EmpireResourceInformation empRes : this.dTemplate.query( Q_RESOURCES , this.mResources , empireId ) ) { + resources.add( empRes ); + } + } + + /** * Get research information * diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireInformation.java index ff5f984..0bee8fb 100644 --- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireInformation.java +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireInformation.java @@ -2,79 +2,140 @@ package com.deepclone.lw.beans.bt.es.data; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; -import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; -@XStreamAlias( "empire" ) +/** + * Empire information record for XML dumps + * + *

+ * This class regroups all "main" empire information in XML dumps. This includes the empire's name + * and identifier, details about the alliance, and the list of resources. + * + * @author E. Benoît + */ +@SuppressWarnings( "serial" ) public class EmpireInformation implements Serializable { - private static final long serialVersionUID = 1L; - + /** The empire's numeric identifier */ @XStreamAsAttribute - @XStreamAlias( "id" ) - private int id; + private Integer id; + /** The empire's name */ @XStreamAsAttribute - @XStreamAlias( "name" ) private String name; + /** The empire's cash */ @XStreamAsAttribute - @XStreamAlias( "cash" ) - private double cash; + private Double cash; + /** + * The alliance the empire belongs to or has requested membership of (or null if + * the empire is neither in an alliance nor requesting to join one) + */ private AllianceInformation alliance; + /** The empire's resources */ + private final ArrayList< EmpireResourceInformation > resources = new ArrayList< EmpireResourceInformation >( ); - public int getId( ) + + /** @return the empire's numeric identifier */ + public Integer getId( ) { - return id; + return this.id; } + /** + * Set the empire's numeric identifier + * + * @param id + * the empire's numeric identifier + */ public void setId( int id ) { this.id = id; } + /** @return the empire's name */ public String getName( ) { - return name; + return this.name; } + /** + * Set the empire's name + * + * @param name + * the empire's name + */ public void setName( String name ) { this.name = name; } - public double getCash( ) + /** @return the amount of cash possessed by the empire */ + public Double getCash( ) { - return cash; + return this.cash; } + /** + * Set the amount of cash possessed by the empire + * + * @param cash + * the amount of cash possessed by the empire + */ public void setCash( double cash ) { this.cash = cash; } + /** + * @return the alliance the empire belongs to or has requested membership of, or + * null if the empire is neither in an alliance nor requesting to join one + */ public AllianceInformation getAlliance( ) { - return alliance; + return this.alliance; } + /** + * Set the information about the alliance + * + * @param alliance + * the information about the alliance + */ public void setAlliance( AllianceInformation alliance ) { this.alliance = alliance; } + + /** + * Access the list of resources + * + * @return the list of resources, even if none was set in the file the instance was loaded from. + */ + public List< EmpireResourceInformation > getResources( ) + { + if ( this.resources == null ) { + return Collections.emptyList( ); + } + return this.resources; + } + } diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireResourceInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireResourceInformation.java new file mode 100644 index 0000000..d6b06f0 --- /dev/null +++ b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireResourceInformation.java @@ -0,0 +1,103 @@ +package com.deepclone.lw.beans.bt.es.data; + + +import java.io.Serializable; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamAsAttribute; + + + +/** + * Empire resources XML dump record + * + *

+ * This class is used to store information about an empire's resources in debugging XML dumps. Each + * instance indicates the amount possessed or owed for a given type of resources. + * + * @author E. Benoît + */ +@XStreamAlias( "resource" ) +@SuppressWarnings( "serial" ) +public class EmpireResourceInformation + implements Serializable +{ + + /** The type of resources */ + @XStreamAlias( "id" ) + @XStreamAsAttribute + private String resource; + + /** The amount of resources possessed */ + @XStreamAsAttribute + private Double possessed; + + /** The amount of resources owed */ + @XStreamAsAttribute + private Double owed; + + + /** @return the type of resources */ + public String getResource( ) + { + return this.resource; + } + + + /** + * Set the type of resources + * + * @param resource + * the type of resources + * + * @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 amount of resources possessed */ + public Double getPossessed( ) + { + return this.possessed; + } + + + /** + * Set the amount of resources possessed + * + * @param possessed + * the amount of resources possessed + */ + public void setPossessed( Double possessed ) + { + this.possessed = possessed; + } + + + /** @return the amount of resources owed */ + public Double getOwed( ) + { + return this.owed; + } + + + /** + * Set the amount of resources owed + * + * @param owed + * the amount of resources owed + */ + public void setOwed( Double owed ) + { + this.owed = owed; + } + +} 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 1d9a23d..dfe0211 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 @@ -1205,6 +1205,30 @@ CREATE VIEW bugs.dump_research_view GRANT SELECT ON bugs.dump_research_view TO :dbuser; +/* + * Empire resources view + * ---------------------- + * + * This view contains the details about empires' resources as they are needed + * by the XML dump generator. + * + * Columns: + * empire_id Identifier of the empire + * resource_name Text-based identifier of the resource type + * empres_possessed Amount of resources possessed by the empire + * empres_owed Amount of resources owed by the empire + */ +DROP VIEW IF EXISTS bugs.dump_emp_resources_view CASCADE; +CREATE VIEW bugs.dump_emp_resources_view + AS SELECT empire_id , name AS resource_name , empres_possessed , empres_owed + FROM emp.resources + INNER JOIN defs.strings ON id = resource_name_id; + +GRANT SELECT + ON bugs.dump_emp_resources_view + TO :dbuser; + + CREATE VIEW bugs.dump_planets_view AS SELECT ep.empire_id , ep.planet_id , p.population , ( ph.current / p.population )::REAL AS current_happiness , ph.target AS target_happiness , @@ -1248,6 +1272,7 @@ GRANT SELECT ON bugs.dump_planets_view TO :dbuser; * if there is no resource provider of that * type on the planet */ +DROP VIEW IF EXISTS bugs.dump_planet_resources_view CASCADE; CREATE VIEW bugs.dump_planet_resources_view AS SELECT empire_id , planet_id , name AS resource_name , diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/005-dump-emp-resources-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/005-dump-emp-resources-view.sql new file mode 100644 index 0000000..104366e --- /dev/null +++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/005-dump-emp-resources-view.sql @@ -0,0 +1,36 @@ +/* + * Tests for bugs.dump_emp_resources_view + */ +BEGIN; + /* + * We need a resource type, an empire and the associated resource record. + */ + \i utils/strings.sql + \i utils/resources.sql + \i utils/accounts.sql + \i utils/naming.sql + \i utils/universe.sql + SELECT _create_resources( 1 , 'resource' ); + SELECT _create_emp_names( 1 , 'empire' ); + INSERT INTO emp.empires( name_id , cash ) + VALUES ( _get_emp_name( 'empire1' ) , 0 ); + INSERT INTO emp.resources( + empire_id , resource_name_id , empres_possessed , empres_owed + ) VALUES ( + _get_emp_name( 'empire1' ) , _get_string( 'resource1' ) , 1 , 2 + ); + + + /***** TESTS BEGIN HERE *****/ + SELECT plan( 1 ); + + SELECT diag_test_name( 'bugs.dump_emp_resources_view - Contents' ); + SELECT set_eq( $$ + SELECT empire_id , resource_name , empres_possessed , empres_owed + FROM bugs.dump_emp_resources_view + $$ , $$ VALUES ( + _get_emp_name( 'empire1' ) , 'resource1' , 1 , 2 + ) $$ ); + + SELECT * FROM finish( ); +ROLLBACK; \ No newline at end of file diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/005-dump-emp-resources-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/005-dump-emp-resources-view.sql new file mode 100644 index 0000000..a1eb0f8 --- /dev/null +++ b/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/005-dump-emp-resources-view.sql @@ -0,0 +1,11 @@ +/* + * Test privileges on bugs.dump_emp_resources_view + */ +BEGIN; + SELECT plan( 1 ); + + SELECT diag_test_name( 'bugs.dump_emp_resources_view - Privileges' ); + SELECT lives_ok( 'SELECT * FROM bugs.dump_emp_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/TestEmpireResourceInformationMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestEmpireResourceInformationMapper.java new file mode 100644 index 0000000..9f8f96d --- /dev/null +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestEmpireResourceInformationMapper.java @@ -0,0 +1,74 @@ +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.beans.bt.es.data.EmpireResourceInformation; +import com.deepclone.lw.testing.MockResultSet; + + + +/** + * Tests for the {@link EmpireResourceInformationMapper} class. + * + * @author E. Benoît + */ +public class TestEmpireResourceInformationMapper +{ + + /** Resource identifier used in tests */ + private static final String TEST_ID = "Test"; + + /** "Owed" value used in tests */ + private static final Double TEST_OWED = 1.0; + + /** "Possessed" value used in tests */ + private static final Double TEST_POSSESSED = 2.0; + + /** The fake result set used in the tests */ + private ResultSet resultSet; + + /** The mapper used in the tests */ + private EmpireResourceInformationMapper mapper; + + + /** Create the mapper and the contents of the fake result set */ + @Before + @SuppressWarnings( "unchecked" ) + public void setUp( ) + { + this.mapper = new EmpireResourceInformationMapper( ); + + HashMap< String , Object > row = new HashMap< String , Object >( ); + row.put( "resource_name" , TEST_ID ); + row.put( "empres_possessed" , TEST_POSSESSED ); + row.put( "empres_owed" , TEST_OWED ); + + this.resultSet = MockResultSet.create( new HashMap[] { + row + } ); + } + + + /** Mapping a row */ + @Test + public void testMapRow( ) + throws SQLException + { + EmpireResourceInformation empRes; + + this.resultSet.absolute( 1 ); + empRes = this.mapper.mapRow( this.resultSet , 1 ); + + assertEquals( TEST_ID , empRes.getResource( ) ); + assertEquals( TEST_POSSESSED , empRes.getPossessed( ) ); + assertEquals( TEST_OWED , empRes.getOwed( ) ); + } +} diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestEmpireResourceInformation.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestEmpireResourceInformation.java new file mode 100644 index 0000000..2f03667 --- /dev/null +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestEmpireResourceInformation.java @@ -0,0 +1,140 @@ +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 EmpireResourceInformation} class. + * + * @author E. Benoît + */ +public class TestEmpireResourceInformation +{ + + /** Resource identifier used in tests */ + private static final String TEST_ID = "Test"; + + /** "Owed" value used in tests */ + private static final Double TEST_OWED = 1.0; + + /** "Possessed" value used in tests */ + private static final Double TEST_POSSESSED = 2.0; + + /** Empire resource information instance used in tests */ + private EmpireResourceInformation empRes; + + + /** Create the instance to be used in actual tests */ + @Before + public void setUp( ) + { + this.empRes = new EmpireResourceInformation( ); + } + + + /** Default values are null */ + @Test + public void testDefaultValues( ) + { + assertNull( this.empRes.getResource( ) ); + assertNull( this.empRes.getOwed( ) ); + assertNull( this.empRes.getPossessed( ) ); + } + + + /** Setting and reading the resource type */ + @Test + public void testResource( ) + { + this.empRes.setResource( TEST_ID ); + assertEquals( TEST_ID , this.empRes.getResource( ) ); + } + + + /** Setting the resource type to null */ + @Test + public void testNullResource( ) + { + try { + this.empRes.setResource( null ); + fail( "InvalidDumpContentsException expected" ); + } catch ( InvalidDumpContentsException exception ) { + assertEquals( EmpireResourceInformation.class , exception.getRecordType( ) ); + assertEquals( "resource" , exception.getField( ) ); + } + } + + + /** Setting and reading the amount of resources possessed */ + @Test + public void testPossessed( ) + { + this.empRes.setPossessed( TEST_POSSESSED ); + assertEquals( TEST_POSSESSED , this.empRes.getPossessed( ) ); + } + + + /** Setting and reading the amount of resources owed */ + @Test + public void testOwed( ) + { + this.empRes.setOwed( TEST_OWED ); + assertEquals( TEST_OWED , this.empRes.getOwed( ) ); + } + + + /** Serialising the instance to XML */ + @Test + public void testXMLSerialisation( ) + { + this.empRes.setResource( TEST_ID ); + this.empRes.setOwed( TEST_OWED ); + this.empRes.setPossessed( TEST_POSSESSED ); + + String serialised = this.createXStreamInstance( ).toXML( this.empRes ); + assertNotNull( serialised ); + assertTrue( serialised.startsWith( "" ) ); + assertTrue( serialised.contains( " id=\"" + TEST_ID + "\"" ) ); + assertTrue( serialised.contains( " owed=\"" + TEST_OWED + "\"" ) ); + assertTrue( serialised.contains( " possessed=\"" + TEST_POSSESSED + "\"" ) ); + } + + + /** Deserialising an instance from XML */ + @Test + public void testXMLDeserialisation( ) + { + String xml = ""; + Object deserialised = this.createXStreamInstance( ).fromXML( xml ); + + assertNotNull( deserialised ); + assertEquals( EmpireResourceInformation.class , deserialised.getClass( ) ); + this.empRes = (EmpireResourceInformation) deserialised; + + assertEquals( TEST_ID , this.empRes.getResource( ) ); + assertEquals( TEST_POSSESSED , this.empRes.getPossessed( ) ); + assertEquals( TEST_OWED , this.empRes.getOwed( ) ); + } + + + /** + * 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( EmpireResourceInformation.class ); + return xstream; + } +}