From 9b346a80c2b0608bcf826947be89cb0d3f8d2a09 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@legacyworlds.com>
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
+ * 
+ * <p>
+ * This class is responsible for transforming rows from <code>bugs.dump_emp_resources_view</code>
+ * into {@link EmpireResourceInformation} instances.
+ * 
+ * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
+ */
+final class EmpireResourceInformationMapper
+		implements RowMapper< EmpireResourceInformation >
+{
+
+	/**
+	 * Map a row from <code>bugs.dump_emp_resources_view</code>
+	 * 
+	 * <p>
+	 * 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
+	 * 
+	 * <p>
+	 * 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
+ * 
+ * <p>
+ * 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 <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
+ */
+@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 <code>null</code> 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
+	 *         <code>null</code> 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
+ * 
+ * <p>
+ * 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 <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
+ */
+@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 <code>null</code>
+	 */
+	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 <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
+ */
+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 <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
+ */
+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 <code>null</code> */
+	@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 <code>null</code> */
+	@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( "<resource " ) );
+		assertTrue( serialised.endsWith( "/>" ) );
+		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 = "<resource id=\"" + TEST_ID + "\" owed=\"" + TEST_OWED.toString( ) + "\" possessed=\""
+				+ TEST_POSSESSED.toString( ) + "\" />";
+		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;
+	}
+}