Compare commits

..

2 commits

Author SHA1 Message Date
ff53af6668 Importing SVN archives - Trunk 2018-10-23 09:43:42 +02:00
fc4c6bd340 Importing SVN archives - B6M1 2018-10-23 09:38:02 +02:00
2263 changed files with 14643 additions and 51691 deletions

8
.gitignore vendored
View file

@ -1,8 +0,0 @@
target
.settings
.classpath
.project
legacyworlds-server-main/data-source.xml
legacyworlds-server-data/db-structure/db-config.txt
*.log
full-debug*.zip

17
.project Normal file
View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>legacyworlds</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

51
build-tools/BUILD.sh Executable file
View file

@ -0,0 +1,51 @@
#!/bin/sh
cd `dirname $0`/..
SRCDIR=`pwd`
if [ "x$1" = "x" ]; then
OUTDIR="$SRCDIR";
else
OUTDIR="$1";
fi
echo "Building Legacy Worlds..."
mvn clean || { echo "Maven clean-up failed"; exit 1; };
mvn package || { echo "Maven build failed"; exit 1; };
echo "Copying files..."
TEMPDIR=`mktemp -d`
mkdir $TEMPDIR/legacyworlds
mkdir $TEMPDIR/legacyworlds/server
mkdir $TEMPDIR/legacyworlds/server/data
mkdir $TEMPDIR/legacyworlds/web
mkdir $TEMPDIR/legacyworlds/sql
# Database and initial data
cp -Rapv legacyworlds-server/legacyworlds-server-data/db-structure/database.sql $TEMPDIR/legacyworlds/sql
cp -Rapv legacyworlds-server/legacyworlds-server-data/db-structure/db-config.txt $TEMPDIR/legacyworlds/sql/db-config-example.txt
cp -Rapv legacyworlds-server/legacyworlds-server-data/db-structure/parts $TEMPDIR/legacyworlds/sql
cp -Rapv legacyworlds-server/legacyworlds-server-main/data/* $TEMPDIR/legacyworlds/server/data
# Server
cp -Rapv legacyworlds-server/legacyworlds-server-main/target/*.jar $TEMPDIR/legacyworlds/server
cp -Rapv legacyworlds-server/legacyworlds-server-main/target/lib $TEMPDIR/legacyworlds/server
cp -Rapv legacyworlds-server/legacyworlds-server-main/data-source.xml $TEMPDIR/legacyworlds/server/data-source-example.xml
# Tools
cp -Rapv build-tools/server-config-example.sh $TEMPDIR/legacyworlds
cp -Rapv build-tools/start-server.sh $TEMPDIR/legacyworlds
cp -Rapv build-tools/stop-server.sh $TEMPDIR/legacyworlds
cp -Rapv build-tools/execute-clit.sh $TEMPDIR/legacyworlds
cp -Rapv build-tools/deploy.sh $TEMPDIR/legacyworlds
# Web sites
cp -Rapv legacyworlds-web/legacyworlds-web-*/target/*.war $TEMPDIR/legacyworlds/web
echo "Preparing archive..."
cd $TEMPDIR
find $TEMPDIR/legacyworlds -type d -name .svn | xargs rm -rf
tar cvjf $OUTDIR/legacyworlds.tar.bz2 legacyworlds || { echo "Archive generation failed"; exit 1; };
echo "Removing temporary directory..."
cd $SRCDIR
rm -rf $TEMPDIR
echo "All done. Legacy Worlds archive: $OUTDIR/legacyworlds.tar.bz2"

34
build-tools/deploy.sh Executable file
View file

@ -0,0 +1,34 @@
#!/bin/sh
COREDIR="$1"
if [ "x$COREDIR" = "x" ] || ! [ -d "$COREDIR" ]; then
echo "Syntax: $0 main_dir tomcat_dir web_dir"
exit 1;
fi
TOMCATDIR="$2"
if [ "x$TOMCATDIR" = "x" ] || ! [ -d "$TOMCATDIR" ]; then
echo "Syntax: $0 main_dir tomcat_dir web_dir"
exit 1;
fi
WEBDIR="$3"
if [ "x$WEBDIR" = "x" ] || ! [ -d "$WEBDIR" ]; then
echo "Syntax: $0 main_dir tomcat_dir web_dir"
exit 1;
fi
cd `dirname $0`
SRCDIR=`pwd`
cp -Rap server web *-*.sh $COREDIR
cd "$TOMCATDIR"
if [ -L "lwmain.war" ]; then
rm -f lwmain.war lwadmin.war
fi
ln -s "$COREDIR/web/legacyworlds-web-main-"*.war lwmain.war
ln -s "$COREDIR/web/legacyworlds-web-admin-"*.war lwadmin.war
cd $WEBDIR
unzip -o $COREDIR/web/legacyworlds-web-main-*.war "css/*" "js/*" "pjirc/*" "img/*"

View file

@ -1,58 +0,0 @@
#!/bin/bash
cd legacyworlds-server-data/db-structure
if ! [ -f db-config.txt ]; then
cat > db-config.txt <<EOF
admin=$USER
db=tests
user=tests
password=tests
EOF
fi
export TEST_DATABASE="`grep ^db= db-config.txt | sed -e s/.*=//`"
export TEST_USER="`grep ^user= db-config.txt | sed -e s/.*=//`"
echo
echo
echo "======================================================================"
echo "LOADING DATABASE DEFINITION ..."
echo "======================================================================"
echo
echo
psql -vQUIET=1 -vON_ERROR_STOP=1 -e --file database.sql || exit 1
if ! [ -d tests/admin ] && ! [ -d tests/user ]; then
echo
echo
echo "WARNING: no unit tests to run"
echo
echo
exit 0
fi
echo
echo
echo "======================================================================"
echo "LOADING TEST FRAMEWORK ..."
echo "======================================================================"
echo
echo
psql -vQUIET=1 -f tests/pgtap.sql $TEST_DATABASE || exit 1
echo
echo
echo "======================================================================"
echo "RUNNING DATABASE TESTS ..."
echo "======================================================================"
echo
echo
cd tests
if [ -d admin ]; then
pg_prove -d $TEST_DATABASE `find admin/ -type f -name '*.sql'` || exit 1
fi
if [ -d user ]; then
pg_prove -U $TEST_USER -d $TEST_DATABASE `find user/ -type f -name '*.sql'` || exit 1
fi
if [ -x dirty/run-dirty-tests.sh ]; then
( cd dirty; exec ./run-dirty-tests.sh ) || exit 1
fi

View file

@ -1,51 +0,0 @@
#!/bin/bash
TESTDIR=`mktemp -d`
cp -Rapv legacyworlds-server-DIST/target/legacyworlds/legacyworlds-server-* $TESTDIR
cd $TESTDIR/legacyworlds-server-*/sql
cat > db-config.txt <<EOF
admin=$USER
db=tests
user=tests
password=tests
EOF
psql -vQUIET=1 -vON_ERROR_STOP=1 -e --file database.sql || exit 1
cd ..
cat > data-source.xml <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean name="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql:tests" />
<property name="username" value="tests" />
<property name="password" value="tests" />
</bean>
</beans>
EOF
java legacyworlds-server-main-*.jar --run-tool ImportText data/i18n-text.xml || exit 1
java legacyworlds-server-main-*.jar --run-tool ImportEvents data/event-definitions.xml || exit 1
java legacyworlds-server-main-*.jar --run-tool ImportResources data/resources.xml || exit 1
java legacyworlds-server-main-*.jar --run-tool ImportTechs data/techs.xml || exit 1
java legacyworlds-server-main-*.jar --run-tool ImportTechGraph data/tech-graph.xml || exit 1
java legacyworlds-server-main-*.jar --run-tool ImportBuildables data/buildables.xml || exit 1
java legacyworlds-server-main-*.jar &
sleep 10
if ! ps ux | grep -q 'java -jar legacyworlds-server-main'; then
exit 1;
fi
java legacyworlds-server-main-*.jar --run-tool Stop || {
killall java
exit 1;
}
java -jar legacyworlds-server-main-1.0.0-0.jar --run-tool CreateUser 'test@example.org 12blah34bleh en' || exit 1
java -jar legacyworlds-server-main-1.0.0-0.jar --run-tool CreateSuperuser 'test@example.org Turlututu' || exit 1

View file

@ -1,67 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>1.0.0</version>
<relativePath>../legacyworlds-server/pom.xml</relativePath>
</parent>
<artifactId>legacyworlds-server-DIST</artifactId>
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
<packaging>pom</packaging>
<name>Legacy Worlds - Server - Packaging</name>
<description>This Maven module is responsible for creating the Legacy Worlds server's packaging.</description>
<!-- Depend solely on the server's JAR, other dependencies will update automatically -->
<dependencies>
<dependency>
<groupId>com.deepclone.lw</groupId>
<artifactId>legacyworlds-server-main</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Clean the target directory before generating the distribution -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<executions>
<execution>
<id>clean-before-assembly</id>
<phase>initialize</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Use the assembly plug-in to generate the distribution -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>distribution-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<attach>false</attach>
<finalName>legacyworlds-server-${project.version}</finalName>
<descriptors>
<descriptor>src/server.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<!-- Legacy Worlds server assembly -->
<id>legacyworlds-server</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<!-- The server's main archive -->
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>.</outputDirectory>
<unpack>false</unpack>
<includes>
<include>com.deepclone.lw:legacyworlds-server-main:jar</include>
</includes>
</dependencySet>
<!-- Libraries - both internal and external dependencies -->
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
<unpack>false</unpack>
<includes>
<include>*:jar</include>
</includes>
<excludes>
<exclude>com.deepclone.lw:legacyworlds-server-main:jar</exclude>
</excludes>
</dependencySet>
</dependencySets>
<fileSets>
<!-- Database definitions -->
<fileSet>
<directory>../legacyworlds-server-data/db-structure</directory>
<outputDirectory>sql</outputDirectory>
<includes>
<include>*.sql</include>
<include>parts/**</include>
<include>db-config.sample.txt</include>
</includes>
</fileSet>
<!-- Default data -->
<fileSet>
<directory>../legacyworlds-server-main/data</directory>
<outputDirectory>data</outputDirectory>
<includes>
<include>i18n/**</include>
<include>**.xml</include>
</includes>
</fileSet>
</fileSets>
<files>
<!-- Data source configuration -->
<file>
<source>../legacyworlds-server-main/data-source.sample.xml</source>
<fileMode>0600</fileMode>
<outputDirectory>.</outputDirectory>
</file>
</files>
</assembly>

View file

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="accountCleanup" class="com.deepclone.lw.beans.acm.AccountCleanupBean" />
<bean id="accountManagement" class="com.deepclone.lw.beans.acm.AccountManagementBean" />
<bean id="adminDao" class="com.deepclone.lw.beans.admin.AdminDAOBean" />
<bean id="administration" class="com.deepclone.lw.beans.admin.AdministrationBean" />
<bean id="adminRecap" class="com.deepclone.lw.beans.admin.AdminRecapBean" />
<bean id="bansDao" class="com.deepclone.lw.beans.admin.BansDAOBean" />
<bean id="bansProcessor" class="com.deepclone.lw.beans.admin.BansProcessorBean" />
<bean id="defaultPreferences" class="com.deepclone.lw.beans.prefs.DefaultPreferencesBean" />
<bean id="ipBan" class="com.deepclone.lw.beans.admin.IpBanBean" />
<bean id="preferenceDefinitions" class="com.deepclone.lw.beans.prefs.PreferenceDefinitionsBean" />
<bean id="preferencesDAO" class="com.deepclone.lw.beans.prefs.PreferencesDAOBean" />
<bean id="preferenceTypesRegistry"
class="com.deepclone.lw.beans.prefs.PreferenceTypesRegistryBean" />
<bean id="quitProcessor" class="com.deepclone.lw.beans.acm.QuitProcessorBean" />
<bean id="requestsExpiration" class="com.deepclone.lw.beans.acm.RequestsExpirationBean" />
<bean id="usersDAO" class="com.deepclone.lw.beans.acm.UsersDAOBean" />
<bean id="userSessionDao" class="com.deepclone.lw.beans.acm.UserSessionDAOBean" />
<bean id="vacationProcessor" class="com.deepclone.lw.beans.acm.VacationProcessorBean" />
</beans>

View file

@ -1,44 +0,0 @@
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.BuildingsInformation;
/**
* Building information row mapper
*
* <p>
* Map rows from <code>bugs.dump_buildings_view</code> into {@link BuildingsInformation} instances.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
final class BuildingsInformationMapper
implements RowMapper< BuildingsInformation >
{
/**
* Map a row from <code>bugs.dump_buildings_view</code>
*
* <p>
* Generate and initialise a {@link BuildingsInformation} instance using the row's fields.
*/
@Override
public BuildingsInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
BuildingsInformation bi = new BuildingsInformation( );
bi.setPlanetId( rs.getInt( "planet_id" ) );
bi.setId( rs.getInt( "building_id" ) );
bi.setName( rs.getString( "building_name" ) );
bi.setAmount( rs.getInt( "amount" ) );
bi.setDamage( rs.getDouble( "damage" ) );
return bi;
}
}

View file

@ -1,65 +0,0 @@
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.AllianceInformation;
import com.deepclone.lw.beans.bt.es.data.DebugInformation;
/**
* Top-level empire summary row mapper
*
* <p>
* This class maps an entry from the database's main empire summary view,
* <code>bugs.dump_main_view</code>, into a top-level {@link DebugInformation} instance.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
final class DebugInformationMapper
implements RowMapper< DebugInformation >
{
/**
* Map a row from <code>bugs.dump_main_view</code> into a {@link DebugInformation} instance
*
* <p>
* Converts the row into a {@link DebugInformation} instance containing system information,
* account information and empire information. If the row contains alliance information, add an
* {@link AllianceInformation} record to the empire information.
*/
@Override
public DebugInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
DebugInformation di = new DebugInformation( );
di.getSystem( ).setNextTick( rs.getLong( "next_tick" ) );
di.getSystem( ).setCurrentTick( (Long) rs.getObject( "current_tick" ) );
di.getAccount( ).setId( rs.getInt( "account_id" ) );
di.getAccount( ).setAddress( rs.getString( "account_address" ) );
di.getAccount( ).setGameCredits( rs.getInt( "game_credits" ) );
di.getAccount( ).setStatus( rs.getString( "account_status" ) );
di.getAccount( ).setLanguage( rs.getString( "account_language" ) );
di.getEmpire( ).setId( rs.getInt( "empire_id" ) );
di.getEmpire( ).setName( rs.getString( "empire_name" ) );
di.getEmpire( ).setCash( rs.getDouble( "cash" ) );
String allianceTag = rs.getString( "alliance_tag" );
if ( allianceTag != null ) {
AllianceInformation alliance = new AllianceInformation( );
alliance.setId( rs.getInt( "alliance_id" ) );
alliance.setTag( allianceTag );
alliance.setPending( rs.getBoolean( "alliance_pending" ) );
di.getEmpire( ).setAlliance( alliance );
}
return di;
}
}

View file

@ -1,52 +0,0 @@
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. If a mining priority is present, set it, otherwise leave the field to its default
* <code>null</code> value.
*/
@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" ) );
int priority = rs.getInt( "mining_priority" );
if ( !rs.wasNull( ) ) {
empRes.setMiningPriority( priority );
}
return empRes;
}
}

View file

@ -1,359 +0,0 @@
package com.deepclone.lw.beans.bt.es;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import com.deepclone.lw.beans.bt.es.data.AccountInformation;
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;
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.ResearchGraphInformation;
import com.deepclone.lw.beans.bt.es.data.ResearchInformation;
import com.deepclone.lw.beans.bt.es.data.ResearchLineInformation;
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;
import com.thoughtworks.xstream.XStream;
/**
* Empire XML summary generator
*
* <p>
* This component is used by the bug tracking system to generate XML dumps of an empire's state. It
* reads the necessary data from the database, convert it to XML dump record classes then serialises
* the whole thing through XStream.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
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 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;
/** 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;
/** XStream instance used to serialise XML dumps */
private final XStream xStream;
/** Top-level row mapper */
private final DebugInformationMapper mMainInfo;
/** Empire resources row mapper */
private final EmpireResourceInformationMapper mResources;
/** Empire research row mapper */
private final ResearchInformationMapper mResearch;
/** 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;
/** Planet buildings information mapper */
private final BuildingsInformationMapper mBuildings;
/** Fleet information row mapper */
private final FleetInformationMapper mFleet;
/** Fleet ships row mapper */
private final ShipsInformationMapper mShips;
/**
* Set up the {@link XStream} instance that generates the dumps as well as the necessary row
* mappers.
*/
public EmpireSummaryBean( )
{
this.xStream = new XStream( );
this.xStream.processAnnotations( new Class< ? >[] {
AccountInformation.class , AllianceInformation.class , BuildingsInformation.class ,
DebugInformation.class , EmpireInformation.class , FleetInformation.class , MovementInformation.class ,
PlanetInformation.class , QueueInformation.class , QueueItemInformation.class ,
ResearchLineInformation.class , ResearchGraphInformation.class , ResourceDeltaInformation.class ,
ResourceProviderInformation.class , ShipsInformation.class , SystemInformation.class
} );
this.mMainInfo = new DebugInformationMapper( );
this.mResources = new EmpireResourceInformationMapper( );
this.mResearch = new ResearchInformationMapper( );
this.mPlanet = new PlanetInformationMapper( );
this.mPlanetResources = new ResourceRowMapper( );
this.mQueueItem = new QueueItemInformationMapper( );
this.mBuildings = new BuildingsInformationMapper( );
this.mFleet = new FleetInformationMapper( );
this.mShips = new ShipsInformationMapper( );
}
/**
* Dependency injector that sets the data source
*
* @param dataSource
* the data source
*/
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new JdbcTemplate( dataSource );
}
/**
* Generate an empire's XML summary
*
* <p>
* Retrieve all information from the database, convert that information into XML dump record
* instances through row mappers, then convert the top-level record into XML using the
* component's {@link XStream} instance.
*/
@Override
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 );
this.getFleets( empireId , empireDump );
return this.xStream.toXML( empireDump );
}
/**
* 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
*
* <p>
* 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
*
* <p>
* 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 );
}
this.getPlanetResources( empireId , planets );
this.getBuildQueues( empireId , planets );
this.getBuildings( empireId , planets );
}
/**
* Add resources information to planets
*
* <p>
* 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
*
* <p>
* 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
*
* <p>
* 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 );
}
}
/**
* Retrieve information about the empire's fleets
*
* <p>
* 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( Q_FLEETS , this.mFleet , empireId ) ) {
empireDump.getFleets( ).add( fi );
fleets.put( fi.getId( ) , fi );
}
this.getShips( empireId , fleets );
}
/**
* Add ships information to fleet records
*
* <p>
* 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 );
}
}
}

View file

@ -1,66 +0,0 @@
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.FleetInformation;
import com.deepclone.lw.beans.bt.es.data.MovementInformation;
/**
* Fleet information row mapper
*
* <p>
* This class is responsible for mapping rows from <code>bugs.dump_fleets_view</code> into
* {@link FleetInformation} instances.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
final class FleetInformationMapper
implements RowMapper< FleetInformation >
{
/**
* Map a row from <code>bugs.dump_fleets_view</code>
*
* <p>
* Generate a {@link FleetInformation} instance from the row's contents. If the row indicates
* that the fleet is moving, add a {@link MovementInformation} instance to the fleet information
* record.
*/
@Override
public FleetInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
FleetInformation fi = new FleetInformation( );
fi.setId( rs.getLong( "fleet_id" ) );
fi.setName( rs.getString( "fleet_name" ) );
fi.setStatus( rs.getString( "status" ) );
fi.setAttacking( rs.getBoolean( "attacking" ) );
fi.setLocationId( rs.getInt( "location_id" ) );
fi.setLocationName( rs.getString( "location_name" ) );
Integer sourceId = (Integer) rs.getObject( "source_id" );
if ( sourceId != null ) {
MovementInformation mi = new MovementInformation( );
mi.setSourceId( sourceId );
mi.setSourceName( rs.getString( "source_name" ) );
mi.setTimeLeft( rs.getInt( "time_left" ) );
mi.setStateTimeLeft( rs.getInt( "state_time_left" ) );
mi.setNearId( (Integer) rs.getObject( "ref_point_id" ) );
mi.setNearName( rs.getString( "ref_point_name" ) );
mi.setOutwards( (Boolean) rs.getObject( "outwards" ) );
mi.setPastRefPoint( (Boolean) rs.getObject( "past_ref_point" ) );
mi.setStartX( (Float) rs.getObject( "start_x" ) );
mi.setStartY( (Float) rs.getObject( "start_y" ) );
fi.setMovement( mi );
}
return fi;
}
}

View file

@ -1,50 +0,0 @@
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.PlanetInformation;
/**
* Top-level planet information row mapper
*
* <p>
* This class maps rows from <code>bugs.dump_planets_view</code> into {@link PlanetInformation}
* instances.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
final class PlanetInformationMapper
implements RowMapper< PlanetInformation >
{
/**
* Map a row from <code>bugs.dump_planets_view</code>
*
* <p>
* Create a new {@link PlanetInformation} instance from the row's contents. The instance's
* civilian and military construction queues, while left mostly uninitialised, will have their
* money and work accumulators set.
*/
@Override
public PlanetInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
PlanetInformation pi = new PlanetInformation( );
pi.setId( rs.getInt( "planet_id" ) );
pi.setPopulation( rs.getDouble( "population" ) );
pi.setCurrentHappiness( rs.getDouble( "current_happiness" ) );
pi.setTargetHappiness( rs.getDouble( "target_happiness" ) );
pi.getCivilianQueue( ).setAccMoney( rs.getDouble( "civ_money" ) );
pi.getCivilianQueue( ).setAccWork( rs.getDouble( "civ_work" ) );
pi.getMilitaryQueue( ).setAccMoney( rs.getDouble( "mil_money" ) );
pi.getMilitaryQueue( ).setAccWork( rs.getDouble( "mil_work" ) );
return pi;
}
}

View file

@ -1,96 +0,0 @@
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
*
* <p>
* Planet resources and resource providers are both extracted from the same
* <code>bugs.planet_resources_view</code> 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 <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
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
*
* <p>
* 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 );
}
}
}

View file

@ -1,46 +0,0 @@
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.QueueItemInformation;
/**
* Generic row mapper for construction queue items
*
* <p>
* This class is responsible for mapping rows from <code>bugs.dump_queues_view</code> into
* {@link QueueItemInformation} instances. These instances will be added to the right queue later.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
final class QueueItemInformationMapper
implements RowMapper< QueueItemInformation >
{
/**
* Map a row from <code>bugs.dump_queues_view</code>
*
* <p>
* Create a {@link QueueItemInformation} instance from the row's contents.
*/
@Override
public QueueItemInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
QueueItemInformation qii = new QueueItemInformation( );
qii.setPlanetId( rs.getInt( "planet_id" ) );
qii.setMilitary( rs.getBoolean( "military" ) );
qii.setId( rs.getInt( "item_id" ) );
qii.setName( rs.getString( "item_name" ) );
qii.setDestroy( rs.getBoolean( "destroy" ) );
qii.setAmount( rs.getInt( "amount" ) );
return qii;
}
}

View file

@ -1,49 +0,0 @@
package com.deepclone.lw.beans.bt.es;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.postgresql.util.PGobject;
import org.springframework.jdbc.core.RowMapper;
import com.deepclone.lw.beans.bt.es.data.ResearchGraphInformation;
import com.deepclone.lw.beans.bt.es.data.ResearchInformation;
import com.deepclone.lw.beans.bt.es.data.TechnologyState;
/**
* Research information row mapper
*
* <p>
* This class maps rows from <code>bugs.dump_research_view</code> into
* {@link ResearchGraphInformation} instances.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
final class ResearchInformationMapper
implements RowMapper< ResearchInformation >
{
/**
* Map a <code>bugs.dump_research_view</code> row
*
* <p>
* Create a {@link ResearchGraphInformation} instance from the row's contents.
*/
@Override
public ResearchInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
ResearchGraphInformation ri = new ResearchGraphInformation( );
ri.setName( rs.getString( "name" ) );
ri.setState( TechnologyState.valueOf( ( (PGobject) rs.getObject( "state" ) ).toString( ) ) );
if ( ri.getState( ) == TechnologyState.RESEARCH ) {
ri.setPoints( rs.getDouble( "points" ) );
ri.setPriority( rs.getInt( "priority" ) );
}
return ri;
}
}

View file

@ -1,65 +0,0 @@
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
*
* <p>
* This class maps rows from <code>bugs.dump_planet_resources_view</code> into
* {@link PlanetResourceRow} instances.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
class ResourceRowMapper
implements RowMapper< PlanetResourceRow >
{
/**
* Map a row from <code>bugs.dump_planet_resources_view</code>
*
* <p>
* 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, and set its mining priority if
* one exists.
*/
@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" ) );
int miningPriority = rs.getInt( "mining_priority" );
if ( !rs.wasNull( ) ) {
rpi.setMiningPriority( miningPriority );
}
row.setProvider( rpi );
}
row.setResource( rs.getString( "resource_name" ) );
return row;
}
}

View file

@ -1,46 +0,0 @@
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.ShipsInformation;
/**
* Fleet ships information row mapper
*
* <p>
* This class is responsible for creating {@link ShipsInformation} instances from the contents of
* <code>bugs.dump_ships_view</code>.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
final class ShipsInformationMapper
implements RowMapper< ShipsInformation >
{
/**
* Map a row from <code>bugs.dump_ships_view</code>
*
* <p>
* Generate a {@link ShipsInformation} instance and initialise its fields based on the row's
* contents.
*/
@Override
public ShipsInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
ShipsInformation si = new ShipsInformation( );
si.setFleetId( rs.getLong( "fleet_id" ) );
si.setId( rs.getInt( "ship_id" ) );
si.setName( rs.getString( "ship_name" ) );
si.setAmount( rs.getInt( "amount" ) );
si.setDamage( rs.getDouble( "damage" ) );
return si;
}
}

View file

@ -1,141 +0,0 @@
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.XStreamAsAttribute;
/**
* 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
{
/** The empire's numeric identifier */
@XStreamAsAttribute
private Integer id;
/** The empire's name */
@XStreamAsAttribute
private String name;
/** The empire's cash */
@XStreamAsAttribute
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 >( );
/** @return the empire's numeric identifier */
public Integer getId( )
{
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 this.name;
}
/**
* Set the empire's name
*
* @param name
* the empire's name
*/
public void setName( String name )
{
this.name = name;
}
/** @return the amount of cash possessed by the empire */
public Double getCash( )
{
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 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;
}
}

View file

@ -1,134 +0,0 @@
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, as well as the
* mining priority if it is a natural resource.
*
* @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;
/**
* The mining priority for this type of resource, or <code>null</code> if it is not a natural
* resource
*/
@XStreamAlias( "mining-priority" )
@XStreamAsAttribute
private Integer miningPriority;
/** @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;
}
/**
* @return the mining priority for this type of resource, or <code>null</code> if it is not a
* natural resource
*/
public Integer getMiningPriority( )
{
return this.miningPriority;
}
/**
* Set the mining priority for this type of resource
*
* @param miningPriority
* the mining priority for this type of resource
*/
public void setMiningPriority( int miningPriority )
{
this.miningPriority = miningPriority;
}
}

View file

@ -1,60 +0,0 @@
package com.deepclone.lw.beans.bt.es.data;
import java.io.Serializable;
/**
* Invalid dump contents exception
*
* <p>
* This runtime exception is thrown by the debugging data record classes when one of the fields is
* set to an incorrect value.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
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;
}
}

View file

@ -1,210 +0,0 @@
package com.deepclone.lw.beans.bt.es.data;
import java.io.Serializable;
import java.util.ArrayList;
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
*
* <p>
* 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.
*
* <p>
* This record exists since version 1 (B6M1) of XML dumps. However, the following changes were made
* later.
* <ul>
* <li>Version 2 (B6M2):
* <ul>
* <li>resource providers added,
* </ul>
* </ul>
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
@XStreamAlias( "planet" )
@SuppressWarnings( "serial" )
public class PlanetInformation
implements Serializable
{
/** Planet identifier */
@XStreamAsAttribute
private Integer id;
/** Planet name */
@XStreamAsAttribute
private String name;
/** Current population of the planet */
@XStreamAlias( "population" )
private Double population;
/** Current happiness of the planet's population */
@XStreamAlias( "current-happiness" )
private Double currentHappiness;
/** Target happiness of the planet's population */
@XStreamAlias( "target-happiness" )
private double targetHappiness;
/** List of buildings */
@XStreamAlias( "buildings" )
private final List< BuildingsInformation > buildings = new ArrayList< BuildingsInformation >( );
/** Civilian construction queue */
@XStreamAlias( "civ-queue" )
private final QueueInformation civilianQueue = new QueueInformation( );
/** Military construction queue */
@XStreamAlias( "mil-queue" )
private final QueueInformation militaryQueue = new QueueInformation( );
/** Planet resource deltas */
@XStreamImplicit
private final ArrayList< ResourceDeltaInformation > resourceDeltas = new ArrayList< ResourceDeltaInformation >( );
/** List of resource providers */
@XStreamImplicit( itemFieldName = "resource-provider" )
private final ArrayList< ResourceProviderInformation > resourceProviders = new ArrayList< ResourceProviderInformation >( );
/** @return the planet's identifier */
public Integer getId( )
{
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 this.name;
}
/**
* Set the planet's name
*
* @param name
* the planet's name
*/
public void setName( String name )
{
this.name = name;
}
/** @return the planet's current population */
public Double getPopulation( )
{
return this.population;
}
/**
* Set the planet's current population
*
* @param population
* the planet's current population
*/
public void setPopulation( double population )
{
this.population = population;
}
/** @return the current happiness of the planet's population */
public Double getCurrentHappiness( )
{
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;
}
/** @return the target happiness of the planet's population */
public Double getTargetHappiness( )
{
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 this.buildings;
}
/** @return the civilian construction queue */
public QueueInformation getCivilianQueue( )
{
return this.civilianQueue;
}
/** @return the military construction queue */
public QueueInformation getMilitaryQueue( )
{
return this.militaryQueue;
}
/** @return the list of resource delta records */
public ArrayList< ResourceDeltaInformation > getResourceDeltas( )
{
return this.resourceDeltas;
}
/** @return the list of resource provider records */
public ArrayList< ResourceProviderInformation > getResourceProviders( )
{
return this.resourceProviders;
}
}

View file

@ -1,136 +0,0 @@
package com.deepclone.lw.beans.bt.es.data;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
/**
* Technology from the technology graph and associated state information
*
* <p>
* This class represents the state of a technology from the B6M2+ technology graph for the empire
* being dumped.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@SuppressWarnings( "serial" )
@XStreamAlias( "technology" )
public class ResearchGraphInformation
extends ResearchInformation
{
/** The technology's name */
@XStreamAsAttribute
private String name;
/** The technology's state */
@XStreamAsAttribute
private TechnologyState state;
/**
* The amount of accumulated research points, or <code>null</code> if the technology has been
* researched
*/
@XStreamAsAttribute
private Double points;
/** The research priority, or <code>null</code> if the technology has been researched */
@XStreamAsAttribute
private Integer priority;
/**
* Gets the technology's name.
*
* @return the technology's name
*/
public String getName( )
{
return this.name;
}
/**
* Sets the technology's name.
*
* @param name
* the technology's new name
*/
public void setName( String name )
{
this.name = name;
}
/**
* Gets the technology's state.
*
* @return the technology's state
*/
public TechnologyState getState( )
{
return this.state;
}
/**
* Sets the technology's state.
*
* @param state
* the technology's new state
*/
public void setState( TechnologyState state )
{
this.state = state;
}
/**
* Gets the amount of accumulated research points
*
* @return the amount of accumulated research points, or <code>null</code> if the technology has
* been researched
*/
public Double getPoints( )
{
return this.points;
}
/**
* Sets the amount of accumulated research points
*
* @param points
* the amount of accumulated research points
*/
public void setPoints( Double points )
{
this.points = points;
}
/**
* Gets the research priority
*
* @return the research priority, or <code>null</code> if the technology has been researched
*/
public Integer getPriority( )
{
return this.priority;
}
/**
* Sets the research priority
*
* @param priority
* the new research priority
*/
public void setPriority( Integer priority )
{
this.priority = priority;
}
}

View file

@ -1,25 +0,0 @@
package com.deepclone.lw.beans.bt.es.data;
import java.io.Serializable;
/**
* Empty, base research record
*
* <p>
* This class used to contain B6M1 research line entries; however, in order to support B6M2
* technologies while maintaining XML compatibility, it has been replaced with an empty class which
* servces as the base class for both old and new records.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
@SuppressWarnings( "serial" )
public abstract class ResearchInformation
implements Serializable
{
// EMPTY
}

View file

@ -1,137 +0,0 @@
package com.deepclone.lw.beans.bt.es.data;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
/**
* Research line information
*
* <p>
* This class defines data stored in the dumps for B6M1 research lines. It is no longer actively
* used as of B6M2, but is kept around so the XML files can still be used if necessary.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@XStreamAlias( "research-line" )
public class ResearchLineInformation
extends ResearchInformation
{
private static final long serialVersionUID = 1L;
/** Identifier of the technology line */
@XStreamAsAttribute
@XStreamAlias( "line" )
private int id;
/** Current level for that line */
@XStreamAsAttribute
@XStreamAlias( "level" )
private int currentLevel;
/** Name of the last level */
@XStreamAsAttribute
@XStreamAlias( "name" )
private String levelName;
/** Accumulated points towards the next level */
@XStreamAsAttribute
@XStreamAlias( "accumulated-points" )
private double accumulated;
/**
* Gets the identifier of the technology line.
*
* @return the identifier of the technology line
*/
public int getId( )
{
return this.id;
}
/**
* Sets the identifier of the technology line.
*
* @param id
* the new identifier of the technology line
*/
public void setId( int id )
{
this.id = id;
}
/**
* Gets the current level for that line.
*
* @return the current level for that line
*/
public int getCurrentLevel( )
{
return this.currentLevel;
}
/**
* Sets the current level for that line.
*
* @param currentLevel
* the new level for that line
*/
public void setCurrentLevel( int currentLevel )
{
this.currentLevel = currentLevel;
}
/**
* Gets the name of the last level.
*
* @return the name of the last level
*/
public String getLevelName( )
{
return this.levelName;
}
/**
* Sets the name of the last level.
*
* @param levelName
* the new name of the last level
*/
public void setLevelName( String levelName )
{
this.levelName = levelName;
}
/**
* Gets the accumulated points towards the next level.
*
* @return the accumulated points towards the next level
*/
public double getAccumulated( )
{
return this.accumulated;
}
/**
* Sets the accumulated points towards the next level.
*
* @param accumulated
* the new accumulated points towards the next level
*/
public void setAccumulated( double accumulated )
{
this.accumulated = accumulated;
}
}

View file

@ -1,109 +0,0 @@
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
*
* <p>
* This class represents records which contain a resource's delta - that is, the income and upkeep
* for some type of resource.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@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 <code>null</code>
*/
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 <code>null</code> 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 <code>null</code> 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;
}
}

View file

@ -1,179 +0,0 @@
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
*
* <p>
* 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.
*
* <p>
* This record exists since version 2 (B6M2) of XML dumps.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@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;
/** Planet-specific mining priority */
@XStreamAlias( "mining-priority" )
@XStreamAsAttribute
private Integer miningPriority;
/** @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 <code>null</code>
*/
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;
}
/**
* @return the planet-specific mining priority, or <code>null</code> if the empire's global
* settings are in used
*/
public Integer getMiningPriority( )
{
return this.miningPriority;
}
/**
* Set the planet-specific mining priority
*
* @param miningPriority
* the planet-specific mining priority
*/
public void setMiningPriority( int miningPriority )
{
this.miningPriority = miningPriority;
}
}

View file

@ -1,20 +0,0 @@
package com.deepclone.lw.beans.bt.es.data;
/**
* State of a (B6M2+) technology
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public enum TechnologyState {
/** The technology is being researched */
RESEARCH ,
/** The technology needs to be implemented */
PENDING ,
/** The technology has been researched and implemented */
KNOWN
}

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="adminErrorMail" class="com.deepclone.lw.beans.eventlog.AdminErrorMailBean" />
<bean id="logCleaner" class="com.deepclone.lw.beans.eventlog.LogCleanerBean" />
<bean id="logger" class="com.deepclone.lw.beans.eventlog.LoggerBean" />
<bean id="logReader" class="com.deepclone.lw.beans.eventlog.LogReaderBean" />
<bean id="logWriter" class="com.deepclone.lw.beans.eventlog.LogWriterBean" />
</beans>

View file

@ -1,15 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server-beans</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>1.0.0</version>
<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
</parent>
<artifactId>legacyworlds-server-beans-events</artifactId>
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
<name>Legacy Worlds - Server - Components - Events</name>
<description>This package defines the components used to process and handle game events.</description>
</project>

View file

@ -1,113 +0,0 @@
package com.deepclone.lw.beans.events;
import javax.sql.DataSource;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
/**
* Events processor component
*
* <p>
* This component acquires the necessary dependencies to create an {@link EventProcessorTask}, does
* so, and registers it with the ticker. It clears the reference to the task when destroyed.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
class EventProcessorBean
implements InitializingBean , DisposableBean
{
/** The ticker */
private Ticker ticker;
/** The Spring transaction template */
private TransactionTemplate tTemplate;
/** The database interface */
private DataSource dataSource;
/** The task */
private Runnable task;
/**
* Dependency injector that sets the ticker component
*
* @param ticker
* the ticker component
*/
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
/**
* Dependency injector that sets the transaction manager
*
* <p>
* Creates the transaction template from the transaction manager
*
* @param tManager
* the Spring transaction manager
*/
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
/**
* Dependency injector that sets the database interface
*
* @param dataSource
* the database interface
*/
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dataSource = dataSource;
}
/**
* Initialise and register the event processing task
*
* <p>
* When the component's dependencies have been injected, this method creates the
* {@link EventProcessorTask} instance and registers it to the ticker.
*/
@Override
public void afterPropertiesSet( )
{
this.task = new EventProcessorTask( this.tTemplate , this.dataSource );
this.ticker.registerTask( Frequency.HIGH , "Events processor" , this.task );
}
/**
* Clear the task reference
*
* <p>
* Remove the reference to the {@link EventProcessorTask} instance, allowing the ticker to clean
* up.
*/
@Override
public void destroy( )
{
this.task = null;
}
}

View file

@ -1,86 +0,0 @@
package com.deepclone.lw.beans.events;
import javax.sql.DataSource;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.utils.StoredProc;
/**
* Event processing task
*
* <p>
* This class implements the task responsible for regular database event processing calls. It is
* registered as a high-frequency ticker task by {@link EventProcessorBean}.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class EventProcessorTask
implements Runnable
{
/** The Spring transaction template */
private final TransactionTemplate tTemplate;
/** The stored procedure that implements event processing */
private final StoredProc eqProcess;
/**
* Initialise the transaction template and stored procedure interface
*
* @param tTemplate
* the transaction template
* @param dataSource
* the database interface
*/
public EventProcessorTask( TransactionTemplate tTemplate , DataSource dataSource )
{
this.tTemplate = tTemplate;
this.eqProcess = new StoredProc( dataSource , "events" , "eq_process" );
this.eqProcess.addOutput( "_result" , java.sql.Types.BOOLEAN );
}
/**
* When the task executes, it will call <code>events.eq_process()</code> repeatedly until the
* stored procedure returns <code>false</code>. Each call is made in a separate transaction.
*/
@Override
public void run( )
{
boolean hasMore;
do {
hasMore = this.processBatch( );
} while ( hasMore );
}
/**
* Process a batch of events
*
* <p>
* This method spawns a transaction in which the <code>events.eq_process()</code> stored
* procedure is called.
*
* @return <code>true</code> if events were processed, <code>false</code> if the queues were
* empty.
*/
private boolean processBatch( )
{
return this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
@Override
public Boolean doInTransaction( TransactionStatus status )
{
return (Boolean) EventProcessorTask.this.eqProcess.execute( ).get( "_result" );
}
} );
}
}

View file

@ -1,16 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server-beans</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>1.0.0</version>
<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
</parent>
<artifactId>legacyworlds-server-beans-i18n</artifactId>
<name>Legacy Worlds - Server - Components - Internationalisation</name>
<description>This package defines the components which control server-side internationalised text management.</description>
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
</project>

View file

@ -1,136 +0,0 @@
package com.deepclone.lw.beans.naming;
import java.util.regex.Pattern;
import com.deepclone.lw.cmd.ObjectNameError;
import com.deepclone.lw.interfaces.naming.ObjectNameValidator;
/**
* Object name validation component
*
* <p>
* This component implements the simple name "pre-validation" component, used before an empire or
* map name is sent to the database.
*
* <p>
* By default, it will accept names that are between 2 and 20 characters. That may be modified in
* the component's initialisation.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class ObjectNameValidatorBean
implements ObjectNameValidator
{
/** Default minimal length */
public static final int MIN_LENGTH = 2;
/** Default maximal length */
public static final int MAX_LENGTH = 20;
/**
* Invalid patterns
*
* <p>
* This constant lists patterns which must be rejected systematically.
*/
private static final Pattern fail[] = {
Pattern.compile( "\\s\\s+" ) , Pattern.compile( "[^A-Za-z0-9 _\\'\\!\\:\\,\\-\\.\\*@\\[\\]\\{\\}]" )
};
/**
* Required patterns
*
* <p>
* This constant lists patters which must be present for a name to be considered valid.
*/
private static final Pattern needed[] = {
Pattern.compile( "[A-Za-z]" )
};
/** Minimal length of a name */
private int minLength = MIN_LENGTH;
/** Maximal length of a name */
private int maxLength = MAX_LENGTH;
/**
* Set the minimal length of a name
*
* @param length
* the new minimal length
*/
public void setMinLength( Integer length )
{
this.minLength = length;
}
/**
* Set the maximal length of a name
*
* @param length
* the new maximal length
*/
public void setMaxLength( Integer length )
{
this.maxLength = length;
}
/*
* (non-Javadoc)
*
* @see com.deepclone.lw.beans.user.ObjectNameValidator#validate(java.lang.String)
*/
@Override
public ObjectNameError validate( String name )
{
return this.validate( name , this.minLength , this.maxLength );
}
/*
* (non-Javadoc)
*
* @see com.deepclone.lw.beans.user.ObjectNameValidator#customValidate(java.lang.String, int,
* int)
*/
@Override
public ObjectNameError validate( String name , int minLength , int maxLength )
{
if ( "".equals( name.trim( ) ) ) {
return ObjectNameError.EMPTY;
}
// No leading or trailing spaces
if ( !name.equals( name.trim( ) ) ) {
return ObjectNameError.INVALID;
}
// Check length
int length = name.length( );
if ( length < minLength || length > maxLength ) {
return ObjectNameError.INVALID;
}
// Check bad patterns
for ( Pattern p : ObjectNameValidatorBean.fail ) {
if ( p.matcher( name ).find( ) ) {
return ObjectNameError.INVALID;
}
}
// Check good patterns
for ( Pattern p : ObjectNameValidatorBean.needed ) {
if ( !p.matcher( name ).find( ) ) {
return ObjectNameError.INVALID;
}
}
return null;
}
}

View file

@ -1,17 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server-beans</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>1.0.0</version>
<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
</parent>
<artifactId>legacyworlds-server-beans-resources</artifactId>
<name>Legacy Worlds - Server - Components - Resources</name>
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
<description>This module contains the components which manage and access in-universe resources, including money and natural resources.</description>
</project>

View file

@ -1,61 +0,0 @@
package com.deepclone.lw.beans.game.resources;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.deepclone.lw.cmd.player.gdata.AbstractResourceRecord;
/**
* Base class for resource information row mappers
*
* <p>
* This class can be used to map resource information rows (for either planets or empires). It
* provides a method which maps the resource information's descriptive fields, and implements
* Spring's {@link RowMapper} for the correct type.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
* @param <RTYPE>
* a resource information record based on {@link AbstractResourceRecord}.
*/
abstract class AbstractResourceMapper< RTYPE extends AbstractResourceRecord >
implements RowMapper< RTYPE >
{
/**
* Extract a resource information row's descriptive fields
*
* <p>
* This method will extract the descriptive fields from a resource information row and store
* them in a resource information instance. It extracts:
* <ul>
* <li>the resource's text identifier,
* <li>the resource's internationalised name,
* <li>the resource's internationalised description,
* <li>the resource's internationalised category name, if there is one.
* </ul>
*
* @param resource
* the resource information record
* @param rs
* the result set with the correct row selected
*
* @throws SQLException
* if a SQLException is encountered getting column values
*/
protected final void getResourceDescription( RTYPE resource , ResultSet rs )
throws SQLException
{
resource.setIdentifier( rs.getString( "resource_identifier" ) );
resource.setTitle( rs.getString( "resource_name" ) );
resource.setDescription( rs.getString( "resource_description" ) );
resource.setCategory( rs.getString( "resource_category" ) );
}
}

View file

@ -1,72 +0,0 @@
package com.deepclone.lw.beans.game.resources;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
/**
* Row mapper for empire resources
*
* <p>
* This class is responsible for converting empire resource information rows into instances of the
* corresponding class, {@link EmpireResourceRecord}.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class EmpireResourceMapper
extends AbstractResourceMapper< EmpireResourceRecord >
{
/**
* Map a row from <code>emp.resources_view</code>
*
* <p>
* This method extracts the resource's description and the fields specific to empire resource
* information from the row, returning the information as an {@link EmpireResourceRecord}
* instance.
*/
@Override
public EmpireResourceRecord mapRow( ResultSet rs , int rowNum )
throws SQLException
{
EmpireResourceRecord resource = new EmpireResourceRecord( );
this.getResourceDescription( resource , rs );
this.getEmpireFields( resource , rs );
return resource;
}
/**
* Read empire-specific resource information from a row
*
* <p>
* This method extracts the stockpiled quantity as well as income and upkeep from the row. If a
* mining setting is set, it extracts it as well.
*
* @param resource
* the empire resource record
* @param rs
* the result set with the correct row selected
*
* @throws SQLException
* if a SQLException is encountered getting column values
*/
private void getEmpireFields( EmpireResourceRecord resource , ResultSet rs )
throws SQLException
{
resource.setStockpiled( rs.getLong( "empres_possessed" ) );
resource.setPlanetUpkeep( rs.getLong( "planets_upkeep" ) );
resource.setIncome( rs.getLong( "planets_income" ) );
resource.setFleetUpkeep( rs.getLong( "fleets_upkeep" ) );
int miningPriority = rs.getInt( "empmset_weight" );
if ( !rs.wasNull( ) ) {
resource.setMiningPriority( miningPriority );
}
}
}

View file

@ -1,65 +0,0 @@
package com.deepclone.lw.beans.game.resources;
import com.deepclone.lw.cmd.player.gdata.PlanetListResourceRecord;
/**
* Intermediary class for planet list resource records extraction
*
* <p>
* This class is used as an intermediary to extract {@link PlanetListResourceRecord} instances from
* <code>emp.plist_resources_view</code>. It contains the instance itself, and an additional field
* which indicates the planet's identifier.
*
* <p>
* Instances of this class are returned by {@link PlanetListResourceRecordMapper} and then processed
* to generate the map returned by {@link ResourcesInformationDAOBean#getPlanetListData(int)}.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
class FullPlanetListRecord
{
/** The planet's identifier */
private int planetId;
/** The resource record */
private final PlanetListResourceRecord record = new PlanetListResourceRecord( );
/**
* Gets the planet's identifier.
*
* @return the planet's identifier
*/
public int getPlanetId( )
{
return this.planetId;
}
/**
* Sets the planet's identifier.
*
* @param planetId
* the new planet's identifier
*/
public void setPlanetId( int planetId )
{
this.planetId = planetId;
}
/**
* Gets the resource record.
*
* @return the resource record
*/
public PlanetListResourceRecord getRecord( )
{
return this.record;
}
}

View file

@ -1,114 +0,0 @@
package com.deepclone.lw.beans.game.resources;
import java.sql.Types;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO;
import com.deepclone.lw.utils.StoredProc;
/**
* Data access component for mining settings
*
* <p>
* This component implements the methods which allow mining settings to be updated by calling the
* appropriate stored procedures.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class MiningSettingsDAOBean
implements MiningSettingsDAO
{
/** <code>emp.mset_update_start(INT)</code> stored procedure */
private StoredProc pStartEmpireUpdate;
/** <code>emp.mset_update_start(INT,INT)</code> stored procedure */
private StoredProc pStartPlanetUpdate;
/** <code>emp.mset_update_set(TEXT,INT)</code> stored procedure */
private StoredProc pSetMiningPriority;
/** <code>emp.mset_update_apply()</code> stored procedure */
private StoredProc pApplyUpdate;
/** <code>emp.mset_toggle_source(INT,INT)</code> stored procedure */
private StoredProc pToggleSource;
/**
* Dependency injector that sets the data source
*
* @param dataSource
* the data source
*/
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.pStartEmpireUpdate = new StoredProc( dataSource , "emp" , "mset_update_start" );
this.pStartEmpireUpdate.addParameter( "_empire" , Types.INTEGER );
this.pStartEmpireUpdate.addOutput( "_success" , Types.BOOLEAN );
this.pStartPlanetUpdate = new StoredProc( dataSource , "emp" , "mset_update_start" );
this.pStartPlanetUpdate.addParameter( "_empire" , Types.INTEGER );
this.pStartPlanetUpdate.addParameter( "_planet" , Types.INTEGER );
this.pStartPlanetUpdate.addOutput( "_success" , Types.BOOLEAN );
this.pSetMiningPriority = new StoredProc( dataSource , "emp" , "mset_update_set" );
this.pSetMiningPriority.addParameter( "_resource" , Types.VARCHAR );
this.pSetMiningPriority.addParameter( "_priority" , Types.INTEGER );
this.pSetMiningPriority.addOutput( "_success" , Types.BOOLEAN );
this.pApplyUpdate = new StoredProc( dataSource , "emp" , "mset_update_apply" );
this.pApplyUpdate.addOutput( "_success" , Types.BOOLEAN );
this.pToggleSource = new StoredProc( dataSource , "emp" , "mset_toggle_source" );
this.pToggleSource.addParameter( "_empire" , Types.INTEGER );
this.pToggleSource.addParameter( "_planet" , Types.INTEGER );
}
/* Documented in interface */
@Override
public boolean startUpdate( int empireId )
{
return (Boolean) this.pStartEmpireUpdate.execute( empireId ).get( "_success" );
}
/* Documented in interface */
@Override
public boolean startUpdate( int empire , int planet )
{
return (Boolean) this.pStartPlanetUpdate.execute( empire , planet ).get( "_success" );
}
/* Documented in interface */
@Override
public boolean setNewPriority( String resource , int priority )
{
return (Boolean) this.pSetMiningPriority.execute( resource , priority ).get( "_success" );
}
/* Documented in interface */
@Override
public boolean applyUpdate( )
{
return (Boolean) this.pApplyUpdate.execute( ).get( "_success" );
}
/* Documented in interface */
@Override
public void togglePlanet( int empire , int planet )
{
this.pToggleSource.execute( empire , planet );
}
}

View file

@ -1,72 +0,0 @@
package com.deepclone.lw.beans.game.resources;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.deepclone.lw.cmd.player.gdata.PlanetListResourceRecord;
/**
* Planet list resource records mapper
*
* <p>
* This class is responsible for mapping rows from <code>emp.plist_resources_view</code> into
* {@link FullPlanetListRecord} instances.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class PlanetListResourceRecordMapper
implements RowMapper< FullPlanetListRecord >
{
/**
* Map a row from <code>emp.plist_resources_view</code>
*
* <p>
* Convert a row from <code>emp.plist_resources_view</code> into a {@link FullPlanetListRecord}
* instance. The resulting instance will have both its planet identifier and actual record set
* according to the row's contents.
*/
@Override
public FullPlanetListRecord mapRow( ResultSet rs , int rowNum )
throws SQLException
{
FullPlanetListRecord fullRecord = new FullPlanetListRecord( );
fullRecord.setPlanetId( rs.getInt( "planet_id" ) );
this.extractRecord( fullRecord.getRecord( ) , rs );
return fullRecord;
}
/**
* Extract the contents of the actual record
*
* <p>
* This method extracts the contents of the record that will be sent to the client from the
* result set.
*
* @param record
* the planet list resource record to update
* @param rs
* the result set to extract information from
*
* @throws SQLException
* if a SQLException is encountered getting column values
*/
private void extractRecord( PlanetListResourceRecord record , ResultSet rs )
throws SQLException
{
record.setName( rs.getString( "resource_name" ) );
record.setIncome( rs.getLong( "pres_income" ) );
record.setUpkeep( rs.getLong( "pres_upkeep" ) );
record.setCivInvestment( rs.getLong( "civ_investment" ) );
record.setMilInvestment( rs.getLong( "mil_investment" ) );
}
}

View file

@ -1,105 +0,0 @@
package com.deepclone.lw.beans.game.resources;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
import com.deepclone.lw.cmd.player.gdata.planets.ResourceProviderRecord;
/**
* Row mapper for planet resources
*
* <p>
* This class maps rows obtained from the planet resources information stored procedure into
* instances of {@link PlanetResourceRecord} which can be sent to a client.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class PlanetResourceMapper
extends AbstractResourceMapper< PlanetResourceRecord >
{
/**
* Map a row from <code>emp.get_planet_resources( )</code>
*
* <p>
* This method extracts fields that are always present, generating the
* {@link PlanetResourceRecord} instance and setting it accordingly, then reads resource
* provider columns and adds a {@link ResourceProviderRecord} instance to the record if
* necessary.
*/
@Override
public PlanetResourceRecord mapRow( ResultSet rs , int rowNum )
throws SQLException
{
PlanetResourceRecord resource = getResourceFields( rs );
getResourceProvider( rs , resource );
return resource;
}
/**
* Map common fields into a {@link PlanetResourceRecord} instance
*
* <p>
* This method creates the instance then reads descriptive fields, then extracts the income,
* upkeep and investment fields.
*
* @param rs
* the JDBC result set that contains the row being extracted
*
* @return the new {@link PlanetResourceRecord} instance with its common fields set
*
* @throws SQLException
* if a SQLException is encountered getting column values
*/
private PlanetResourceRecord getResourceFields( ResultSet rs )
throws SQLException
{
PlanetResourceRecord resource = new PlanetResourceRecord( );
this.getResourceDescription( resource , rs );
resource.setIncome( rs.getLong( "pres_income" ) );
resource.setUpkeep( rs.getLong( "pres_upkeep" ) );
resource.setInvested( rs.getLong( "pres_invested" ) );
return resource;
}
/**
* Map resource provider fields if they are present.
*
* <p>
* Check if the record includes resource provider information. If it does, extract the fields'
* values into a {@link ResourceProviderRecord} instance and add it to the
* {@link PlanetResourceRecord}.
*
* @param rs
* the JDBC result set that contains the row being extracted
* @param resource
* the {@link PlanetResourceRecord} instance to add information to
*
* @throws SQLException
* if a SQLException is encountered getting column values
*/
private void getResourceProvider( ResultSet rs , PlanetResourceRecord resource )
throws SQLException
{
long capacity = rs.getLong( "resprov_capacity" );
if ( rs.wasNull( ) ) {
return;
}
ResourceProviderRecord provider = new ResourceProviderRecord( );
provider.setCapacity( capacity );
provider.setQuantity( rs.getLong( "resprov_quantity" ) );
provider.setDifficulty( rs.getInt( "resprov_difficulty" ) );
provider.setPriority( rs.getInt( "mset_weight" ) );
resource.setResourceProvider( provider );
}
}

View file

@ -1,107 +0,0 @@
package com.deepclone.lw.beans.game.resources;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO;
import com.deepclone.lw.interfaces.game.resources.ResourcesController;
/**
* Resources controller component
*
* <p>
* This component implements all game actions that affect resources or resource-related information,
* such as mining priorities.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@Transactional
class ResourcesControllerBean
implements ResourcesController
{
/** The mining settings access interface */
private MiningSettingsDAO settings;
/**
* Dependency injector that sets the mining settings access interface
*
* @param settings
* the mining settings access interface
*/
@Autowired( required = true )
public void setMiningSettingsDAO( MiningSettingsDAO settings )
{
this.settings = settings;
}
/**
* Update an empire's mining settings
*
* <p>
* Start a mining settings update for the specified empire, then set each resource-specific
* priority, then apply the update. Exit whenever something goes wrong.
*/
@Override
public void updateEmpireSettings( int empireId , Map< String , Integer > settings )
{
if ( this.settings.startUpdate( empireId ) ) {
this.sendMiningSettings( settings );
}
}
/* Documented in interface */
@Override
public void togglePlanet( int empire , int planet )
{
this.settings.togglePlanet( empire , planet );
}
/**
* Update a planet's mining settings
*
* <p>
* Start a mining settings update for the specified planet / empire combination, then set each
* resource-specific priority, then apply the update. Exit whenever something goes wrong.
*/
@Override
public void updatePlanetSettings( int empire , int planet , Map< String , Integer > settings )
{
if ( this.settings.startUpdate( empire , planet ) ) {
this.sendMiningSettings( settings );
}
}
/**
* Send mining settings to the database
*
* <p>
* This method is called once a mining settings update has been started (whether it's a
* planet-specific or empire-wide update). It sends all settings to the database server, and
* aborts if anything goes wrong.
*
* @param settings
* the settings to upload
*/
private void sendMiningSettings( Map< String , Integer > settings )
{
for ( Map.Entry< String , Integer > entry : settings.entrySet( ) ) {
if ( !this.settings.setNewPriority( entry.getKey( ) , entry.getValue( ) ) ) {
return;
}
}
this.settings.applyUpdate( );
}
}

View file

@ -1,140 +0,0 @@
package com.deepclone.lw.beans.game.resources;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import com.deepclone.lw.cmd.player.gdata.PlanetListResourceRecord;
import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
import com.deepclone.lw.interfaces.game.resources.ResourcesInformationDAO;
/**
* Resource information access component
*
* <p>
* This component's goal is to read information about resources from the database and return the
* records in some usable format.
*
* <p>
* It does not contain any method that actually change the database.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
class ResourcesInformationDAOBean
implements ResourcesInformationDAO
{
/** SQL query that fetches a planet's resources information */
private static final String Q_PLANET_RESOURCES = "SELECT * FROM emp.get_planet_resources( ? )";
/** SQL query that fetches an empire's resources information */
private static final String Q_EMPIRE_RESOURCES = "SELECT * FROM emp.resources_view WHERE empire_id = ?";
/** SQL query that fetches the resource records for an empire's planet list */
private static final String Q_PLIST_RESOURCES = "SELECT * FROM emp.plist_resources_view WHERE empire_id = ?";
/** Row mapper for planet resources */
private final PlanetResourceMapper mPlanetResource;
/** Row mapper for empire resources */
private final EmpireResourceMapper mEmpireResource;
/** Row mapper for planet list records */
private final PlanetListResourceRecordMapper mPlanetListRecord;
/** Spring JDBC interface */
private JdbcTemplate dTemplate;
/** Initialise the necessary row mappers */
public ResourcesInformationDAOBean( )
{
this.mPlanetResource = new PlanetResourceMapper( );
this.mEmpireResource = new EmpireResourceMapper( );
this.mPlanetListRecord = new PlanetListResourceRecordMapper( );
}
/**
* Dependency injector that sets the data source
*
* @param dataSource
* the data source
*/
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new JdbcTemplate( dataSource );
}
/**
* Run the planet resources information query and extract the data
*
* <p>
* This implementation simply executes a query using the <code>emp.get_planet_resources()</code>
* stored procedure and maps the resulting rows into a list of {@link PlanetResourceRecord}
* instances.
*/
@Override
public List< PlanetResourceRecord > getPlanetInformation( int planet )
{
return this.dTemplate.query( Q_PLANET_RESOURCES , this.mPlanetResource , planet );
}
/**
* Run the empire resources information query and extract the data
*
* <p>
* This implementation executes a query on <code>emp.resources_view</code> for a specific
* empire, and maps the resulting rows into a list of {@link EmpireResourceRecord} instances.
*/
@Override
public List< EmpireResourceRecord > getEmpireInformation( int empire )
{
return this.dTemplate.query( Q_EMPIRE_RESOURCES , this.mEmpireResource , empire );
}
/**
* Run the planet list resources query and extract the data
*
* <p>
* This implementation queries <code>emp.plist_resources_view</code> to obtain the planet list's
* records, then maps the resulting rows using the intermediary {@link FullPlanetListRecord}
* class, and finally associates records to the corresponding planet identifiers.
*/
@Override
public Map< Integer , List< PlanetListResourceRecord > > getPlanetListData( int empire )
{
Map< Integer , List< PlanetListResourceRecord > > result;
result = new HashMap< Integer , List< PlanetListResourceRecord > >( );
List< FullPlanetListRecord > queryOutput;
queryOutput = this.dTemplate.query( Q_PLIST_RESOURCES , this.mPlanetListRecord , empire );
for ( FullPlanetListRecord fullRecord : queryOutput ) {
List< PlanetListResourceRecord > records = result.get( fullRecord.getPlanetId( ) );
if ( records == null ) {
records = new LinkedList< PlanetListResourceRecord >( );
result.put( fullRecord.getPlanetId( ) , records );
}
records.add( fullRecord.getRecord( ) );
}
return result;
}
}

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="miningSettingsDAO" class="com.deepclone.lw.beans.game.resources.MiningSettingsDAOBean" />
<bean id="resourcesController" class="com.deepclone.lw.beans.game.resources.ResourcesControllerBean" />
<bean id="resourcesInformationDAO" class="com.deepclone.lw.beans.game.resources.ResourcesInformationDAOBean" />
</beans>

View file

@ -1,14 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server-beans</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>1.0.0</version>
<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
</parent>
<artifactId>legacyworlds-server-beans-simple</artifactId>
<name>Legacy Worlds - Server - Components - Simple game</name>
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
<description>This module contains code that corresponds to a simple "placeholder" game. This code should become obsolete over time, as it is being replaced with actual LWB6 code, until the module can finally be removed.</description>
</project>

View file

@ -1,36 +0,0 @@
package com.deepclone.lw.beans.empire;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.deepclone.lw.sqld.game.GeneralInformation;
class GeneralInformationRowMapper
implements RowMapper< GeneralInformation >
{
@Override
public GeneralInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
GeneralInformation info = new GeneralInformation( );
info.setName( rs.getString( "name" ) );
info.setTag( rs.getString( "alliance" ) );
info.setCash( rs.getLong( "cash" ) );
info.setLanguage( rs.getString( "language" ) );
info.setNextTick( rs.getLong( "game_time" ) );
info.setAccountId( rs.getInt( "account_id" ) );
String statusString = rs.getString( "status" );
info.setStatus( rs.wasNull( ) ? null : statusString.charAt( 0 ) );
return info;
}
}

View file

@ -1,26 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server-beans</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>1.0.0</version>
<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
</parent>
<artifactId>legacyworlds-server-beans-technologies</artifactId>
<name>Legacy Worlds - Server - Components - Technologies</name>
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
<description>This module contains the components which manage and access in-universe technologies.</description>
<dependencies>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
</project>

View file

@ -1,143 +0,0 @@
package com.deepclone.lw.beans.game.technologies;
import java.sql.Types;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
import com.deepclone.lw.interfaces.game.technologies.PlayerTechnologiesDAO;
import com.deepclone.lw.utils.StoredProc;
/**
* Data access component for player technologies
*
* <p>
* This class implements database queries and calls to stored procedures which allow players to
* access and manage their empires' research.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class PlayerTechnologiesDAOBean
implements PlayerTechnologiesDAO
{
/** SQL query that fetches an empire's research state */
private static final String Q_EMPIRE_RESEARCH = "SELECT * FROM emp.technologies_view WHERE empire_id = ?";
/** Row mapper for research state entries */
private final ResearchRowMapper mResearch;
/** Stored procedure that initiates a research priority update */
private StoredProc fResprioUpdateStart;
/** Stored procedure that uploads a single research priority */
private StoredProc fResprioUpdateSet;
/** Stored procedure that applies a research priority update */
private StoredProc fResprioUpdateApply;
/** Stored procedure that implements a technology */
private StoredProc fTechnologyImplement;
/** Spring JDBC interface */
private JdbcTemplate dTemplate;
/** Initialise the necessary row mappers */
public PlayerTechnologiesDAOBean( )
{
this.mResearch = new ResearchRowMapper( );
}
/**
* Dependency injector that sets the data source and initialises stored procedures
*
* @param dataSource
* the data source
*/
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new JdbcTemplate( dataSource );
this.fResprioUpdateStart = new StoredProc( dataSource , "emp" , "resprio_update_start" )
.addParameter( "_empire" , Types.INTEGER )
.addOutput( "_result" , Types.BOOLEAN );
this.fResprioUpdateSet = new StoredProc( dataSource , "emp" , "resprio_update_set" )
.addParameter( "_technology" , Types.VARCHAR )
.addParameter( "_priority" , Types.INTEGER )
.addOutput( "_result" , Types.BOOLEAN );
this.fResprioUpdateApply = new StoredProc( dataSource , "emp" , "resprio_update_apply" )
.addOutput( "_result" , Types.BOOLEAN );
this.fTechnologyImplement = new StoredProc( dataSource , "emp" , "technology_implement" )
.addParameter( "_empire" , Types.INTEGER )
.addParameter( "_technology" , Types.VARCHAR )
.addOutput( "_result" , Types.BOOLEAN );
}
/**
* Query and map research entries for an empire
*
* <p>
* Run the query against <code>emp.technologies_view</code> then map all rows using a
* {@link ResearchRowMapper}.
*/
@Override
public List< ResearchData > getResearchData( int empire )
{
return this.dTemplate.query( Q_EMPIRE_RESEARCH , this.mResearch , empire );
}
/**
* Call <code>emp.resprio_update_start</code>
*/
@Override
public boolean startPriorityUpdate( int empire )
{
return (Boolean) this.fResprioUpdateStart.execute( empire ).get( "_result" );
}
/**
* Call <code>emp.resprio_update_set</code>
*/
@Override
public boolean uploadResearchPriority( String identifier , int priority )
{
return (Boolean) this.fResprioUpdateSet.execute( identifier , priority ).get( "_result" );
}
/**
* Call <code>emp.resprio_update_apply</code>
*/
@Override
public boolean applyPriorityUpdate( )
{
return (Boolean) this.fResprioUpdateApply.execute( ).get( "_result" );
}
/**
* Call <code>emp.technology_implement</code>
*/
@Override
public boolean implement( int empire , String technology )
{
return (Boolean) this.fTechnologyImplement.execute( empire , technology ).get( "_result" );
}
}

View file

@ -1,224 +0,0 @@
package com.deepclone.lw.beans.game.technologies;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.deepclone.lw.cmd.player.gdata.GamePageData;
import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
import com.deepclone.lw.cmd.player.tech.GetResearchResponse;
import com.deepclone.lw.interfaces.game.EmpireManagement;
import com.deepclone.lw.interfaces.game.technologies.PlayerTechnologiesDAO;
import com.deepclone.lw.interfaces.game.technologies.ResearchController;
import com.deepclone.lw.interfaces.i18n.TranslationException;
import com.deepclone.lw.interfaces.i18n.Translator;
/**
* Research control component
*
* <p>
* This component implements all actions allowing a player to view and update its empire's research
* state.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@Transactional
class ResearchControllerBean
implements ResearchController
{
/** Main empire management component */
private EmpireManagement empireManagement;
/** String translator */
private Translator translator;
/** Data access object for technologies */
private PlayerTechnologiesDAO playerTechnologiesDAO;
/**
* Dependency injector that sets the empire management component
*
* @param empireManagement
* the empire management component
*/
@Autowired( required = true )
public void setEmpireManagement( EmpireManagement empireManagement )
{
this.empireManagement = empireManagement;
}
/**
* Dependency injector that sets the translation component
*
* @param translator
* the translation component
*/
@Autowired( required = true )
public void setTranslator( Translator translator )
{
this.translator = translator;
}
/**
* Dependency injector that sets the data access object for technologies
*
* @param playerTechnologiesDAO
* the data access object for technologies
*/
@Autowired( required = true )
public void setPlayerTechnologiesDAO( PlayerTechnologiesDAO playerTechnologiesDAO )
{
this.playerTechnologiesDAO = playerTechnologiesDAO;
}
/**
* Get the raw research data from the database, then handle translation and dependencies
*
* <p>
* In order to generate the response, this method fetches the raw research state information
* from the database. It then proceeds with translating all categories, names and descriptions,
* then adds reverse dependency information to all loaded technologies.
*/
@Override
public GetResearchResponse getResearchData( int empire )
{
GamePageData pageData = this.empireManagement.getGeneralInformation( empire );
List< ResearchData > technologies = this.playerTechnologiesDAO.getResearchData( empire );
// Translate categories, names and descriptions
Map< String , String > translations = this.getTranslationsFor( technologies , pageData.getLanguage( ) );
Map< String , ResearchData > byId = new HashMap< String , ResearchData >( );
for ( ResearchData tech : technologies ) {
byId.put( tech.getIdentifier( ) , tech );
tech.setCategory( translations.get( tech.getCategory( ) ) );
if ( tech.getName( ) != null ) {
tech.setName( translations.get( tech.getName( ) ) );
tech.setDescription( translations.get( tech.getDescription( ) ) );
}
tech.setBuildings( this.translateList( tech.getBuildings( ) , translations ) );
}
// Add reverse dependency identifiers
for ( ResearchData tech : technologies ) {
for ( String dependency : tech.getDependencies( ) ) {
byId.get( dependency ).addReverseDependency( tech.getIdentifier( ) );
}
}
return new GetResearchResponse( pageData , technologies );
}
/**
* Get translations used by a list of raw research entries
*
* <p>
* This method is fed the raw research state data from the player technologies data access
* object. It generates a set of string identifiers which contains all categories, names and
* descriptions, then fetches these strings' translations.
*
* @param technologies
* the research state data from the DAO
* @param language
* the player's selected language
*
* @return the map of string identifiers to string contents
*/
private Map< String , String > getTranslationsFor( List< ResearchData > technologies , String language )
{
Set< String > identifiers = new HashSet< String >( );
for ( ResearchData tech : technologies ) {
identifiers.add( tech.getCategory( ) );
if ( tech.getName( ) != null ) {
identifiers.add( tech.getName( ) );
identifiers.add( tech.getDescription( ) );
}
identifiers.addAll( tech.getBuildings( ) );
}
try {
return this.translator.translate( language , identifiers );
} catch ( TranslationException e ) {
throw new RuntimeException( "error while translating technology-related data" , e );
}
}
/**
* Translate a list of strings
*
* <p>
* This method fetches translations for a list of string identifiers.
*
* @param input
* the list of strings to translate
* @param translations
* the map of translations returned by {@link #getTranslationsFor(List, String)}
*
* @return the translated list of strings
*/
private List< String > translateList( List< String > input , Map< String , String > translations )
{
ArrayList< String > result = new ArrayList< String >( input.size( ) );
for ( String str : input ) {
result.add( translations.get( str ) );
}
return result;
}
/**
* Update research priorities
*
* <p>
* This method will start a research priority update for the specified empire, then upload each
* value in the map to the database. Finally, it will try to apply the update.
*
* <p>
* If any of the above steps fail, the method will abort.
*/
@Override
public boolean updatePriorities( int empire , Map< String , Integer > priorities )
{
if ( !this.playerTechnologiesDAO.startPriorityUpdate( empire ) ) {
return false;
}
for ( Map.Entry< String , Integer > entry : priorities.entrySet( ) ) {
if ( !this.playerTechnologiesDAO.uploadResearchPriority( entry.getKey( ) , entry.getValue( ) ) ) {
return false;
}
}
return this.playerTechnologiesDAO.applyPriorityUpdate( );
}
/**
* Implement a technology
*
* <p>
* Call the DAO's technology implementation method in order to access the corresponding stored
* procedure.
*/
@Override
public boolean implement( int empire , String technology )
{
return this.playerTechnologiesDAO.implement( empire , technology );
}
}

View file

@ -1,95 +0,0 @@
package com.deepclone.lw.beans.game.technologies;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.postgresql.util.PGobject;
import org.springframework.jdbc.core.RowMapper;
import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
/**
* Row mapper for empire research state entries
*
* <p>
* This class is responsible for converting empire research state information rows into instances of
* the corresponding class, {@link ResearchData}. The instances it produces are "raw": they contain
* string identifiers instead of translations, and their reverse dependencies are not set.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
class ResearchRowMapper
implements RowMapper< ResearchData >
{
/**
* Map a row from <code>emp.technologies_view</code>
*
* <p>
* This method maps a single row from the <code>emp.technologies_view</code> view into a
* {@link ResearchData} instance.
*/
@Override
public ResearchData mapRow( ResultSet rs , int rowNum )
throws SQLException
{
ResearchData output = new ResearchData( );
output.setIdentifier( rs.getString( "emptech_id" ) );
output.setCategory( rs.getString( "technology_category" ) );
if ( rs.getBoolean( "emptech_visible" ) ) {
output.setName( rs.getString( "technology_name" ) );
output.setDescription( rs.getString( "technology_description" ) );
output.setPrice( rs.getLong( "technology_price" ) );
}
int ratio = rs.getInt( "emptech_ratio" );
if ( rs.wasNull( ) ) {
String state = ( (PGobject) rs.getObject( "emptech_state" ) ).getValue( );
output.setImplemented( "KNOWN".equals( state ) );
} else {
output.setCompletion( ratio );
output.setPriority( rs.getInt( "emptech_priority" ) );
}
output.setDependencies( this.splitField( rs , "technology_dependencies" ) );
output.setBuildings( this.splitField( rs , "technology_buildings" ) );
return output;
}
/**
* Extract a comma-separated field
*
* <p>
* This method accesses then extracts the contents of a comma-separated field (for example
* dependencies or unlocked buildings).
*
* @param rs
* the SQL result set
* @param field
* the field's name
*
* @return an array of strings containing the field's values
*
* @throws SQLException
* if something goes wrong while accessing the field
*/
private String[] splitField( ResultSet rs , String field )
throws SQLException
{
String fValue = rs.getString( field );
if ( fValue == null || "".equals( fValue ) ) {
return new String[ 0 ];
}
return fValue.split( "," );
}
}

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="playerTechnologiesDAO" class="com.deepclone.lw.beans.game.technologies.PlayerTechnologiesDAOBean" />
<bean id="reesearchController" class="com.deepclone.lw.beans.game.technologies.ResearchControllerBean" />
</beans>

View file

@ -1,17 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server-beans</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>1.0.0</version>
<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
</parent>
<artifactId>legacyworlds-server-beans-updates</artifactId>
<name>Legacy Worlds - Server - Components - Game updates</name>
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
<description>This module contains the components which process the game updates and allow the administration interface to display information about them.</description>
</project>

View file

@ -1,238 +0,0 @@
package com.deepclone.lw.beans.updates;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.cmd.admin.logs.LogLevel;
import com.deepclone.lw.interfaces.eventlog.Logger;
import com.deepclone.lw.interfaces.eventlog.SystemLogger;
import com.deepclone.lw.interfaces.game.updates.GameUpdateProcessor;
import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
import com.deepclone.lw.interfaces.sys.MaintenanceStatusException;
import com.deepclone.lw.interfaces.sys.SystemStatus;
import com.deepclone.lw.interfaces.sys.TickStatusException;
/**
* Game update processor component
*
* <p>
* This component implements game updates processing. It will update the system status as necessary,
* checking for maintenance mode, and of course implement the necessary operations for game updates.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class GameUpdateProcessorBean
implements GameUpdateProcessor
{
/** System state management component */
private SystemStatus systemStatus;
/** Logger used by this component */
private SystemLogger logger;
/** Transaction template used to run update batches */
private TransactionTemplate tTemplate;
/** Update processing database interface */
private UpdatesDAO updatesDao;
/** Server-level update processors registry */
private ServerProcessorRegistry registry;
/** Game update processor lock */
private boolean executing;
/**
* Dependency injector that sets the sytstem state management component
*
* @param systemStatus
* the sytstem state management component
*/
@Autowired( required = true )
public void setSystemStatus( SystemStatus systemStatus )
{
this.systemStatus = systemStatus;
}
/**
* Dependency injector that initialises the logger from the logging component
*
* @param logger
* the logging component
*/
@Autowired( required = true )
public void setLogger( Logger logger )
{
this.logger = logger.getSystemLogger( "GameUpdate" );
}
/**
* Dependency injector that initialises the transaction template from the transaction manager
*
* @param transactionManager
* the transaction manager
*/
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager transactionManager )
{
this.tTemplate = new TransactionTemplate( transactionManager );
}
/**
* Dependency injector that sets the database access component for game updates
*
* @param updatesDao
* the database access component for game updates
*/
@Autowired( required = true )
public void setUpdatesDAO( UpdatesDAO updatesDao )
{
this.updatesDao = updatesDao;
}
/**
* Dependency injector that sets the processor registry
*
* @param registry
* the processor registry
*/
@Autowired( required = true )
public void setRegistry( ServerProcessorRegistry registry )
{
this.registry = registry;
}
/**
* Try and lock the processor
*
* <p>
* Test the {@link #executing} field, setting it to <code>true</code> and returning
* <code>true</code> if it wasn't or returning <code>false</code> if it was.
*/
@Override
public synchronized boolean tryLock( )
{
if ( this.executing ) {
return false;
}
this.executing = true;
return true;
}
/**
* Unlock the processor
*
* <p>
* Set {@link #executing} back to <code>false</code>. If it was already set to
* <code>false</code>, throw an {@link IllegalStateException}.
*/
@Override
public synchronized void unlock( )
throws IllegalStateException
{
if ( !this.executing ) {
throw new IllegalStateException( "Trying to unlock game update processor, but it isn't locked" );
}
this.executing = false;
}
/**
* Check for an unfinished update cycle and terminate it
*
* <p>
* Check for a "stuck" update cycle. If there is one, issue a warning and process it through the
* {@link #executeTick(long)} method.
*/
@Override
public boolean endPreviousCycle( )
{
Long currentTick;
try {
currentTick = this.systemStatus.checkStuckTick( );
} catch ( MaintenanceStatusException e ) {
return true;
}
if ( currentTick == null ) {
return false;
}
this.logger.log( LogLevel.WARNING , "Tick " + currentTick + " restarted" ).flush( );
this.executeTick( currentTick );
return true;
}
/**
* Execute an update cycle
*
* <p>
* Start by checking for, and executing if necessary, a "stuck" update cycle. If one is found,
* return. Otherwise, start a new tick through the system state manager, and call
* {@link #executeTick(long)} to process it.
*
* <p>
* If maintenance mode is active, the new tick will not be started.
*/
@Override
public void executeUpdateCycle( )
{
// Attempt to end the previous tick, if e.g. maintenance mode was initiated while it was
// being processed
if ( this.endPreviousCycle( ) ) {
return;
}
// Initiate next tick
long tickId;
try {
tickId = this.systemStatus.startTick( );
} catch ( TickStatusException e ) {
throw new RuntimeException( "tick initiated while previous tick still being processed" , e );
} catch ( MaintenanceStatusException e ) {
return;
}
// Execute tick
this.logger.log( LogLevel.DEBUG , "Tick " + tickId + " started" ).flush( );
this.executeTick( tickId );
}
/**
* Process all remaining update batches for an update cycle
*
* <p>
* This method will try and process all update batches using a {@link GameUpdateTransaction}
* instance. It loops until the transaction indicates that no further updates are to be
* processed. However, the loop will exit if maintenance mode becomes active between update
* batches.
*
* @param tickId
* the game update cycle's identifier
*/
private void executeTick( final long tickId )
{
GameUpdateTransaction transaction = new GameUpdateTransaction( this.updatesDao , this.registry , tickId );
while ( !this.tTemplate.execute( transaction ) ) {
if ( this.systemStatus.checkMaintenance( ) != null ) {
this.logger.log( LogLevel.INFO , "Tick " + tickId + " interrupted by system maintenance" ).flush( );
return;
}
}
this.logger.log( LogLevel.TRACE , "Tick " + tickId + " completed" ).flush( );
}
}

View file

@ -1,96 +0,0 @@
package com.deepclone.lw.beans.updates;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import com.deepclone.lw.interfaces.game.updates.GameUpdateProcessor;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
/**
* Game update ticker task
*
* <p>
* This component will register itself as a ticker task to be executed once per minute. When it
* runs, it will try and execute an update cycle.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class GameUpdateTaskBean
implements InitializingBean , Runnable
{
/** The ticker component */
private Ticker ticker;
/** The game updates processor */
private GameUpdateProcessor gameUpdateProcessor;
/**
* Dependency injector that sets the ticker component
*
* @param ticker
* the ticker component
*/
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
/**
* Dependency injector that sets the game update processor
*
* @param gameUpdateProcessor
* the game update processor
*/
@Autowired( required = true )
public void setGameUpdateProcessor( GameUpdateProcessor gameUpdateProcessor )
{
this.gameUpdateProcessor = gameUpdateProcessor;
}
/**
* Finish a previous update cycle if there is one, then register the component to the ticker
*/
@Override
public void afterPropertiesSet( )
{
if ( this.gameUpdateProcessor.tryLock( ) ) {
try {
this.gameUpdateProcessor.endPreviousCycle( );
} finally {
this.gameUpdateProcessor.unlock( );
}
}
this.ticker.registerTask( Frequency.MINUTE , "Game update" , this );
}
/**
* Run a game update cycle
*
* <p>
* Try locking the game update processor. On success, execute an update cycle, then unlock the
* processor.
*/
@Override
public void run( )
{
if ( !this.gameUpdateProcessor.tryLock( ) ) {
return;
}
try {
this.gameUpdateProcessor.executeUpdateCycle( );
} finally {
this.gameUpdateProcessor.unlock( );
}
}
}

View file

@ -1,89 +0,0 @@
package com.deepclone.lw.beans.updates;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import com.deepclone.lw.interfaces.game.updates.UpdateBatchProcessor;
import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
import com.deepclone.lw.sqld.sys.GameUpdateResult;
/**
* Game update transaction
*
* <p>
* This class is responsible for executing the necessary operations during a game update
* transaction. It is used by the {@link GameUpdateProcessorBean} component to implement its main
* processing loop.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class GameUpdateTransaction
implements TransactionCallback< Boolean >
{
/** The game updates database access interface */
private final UpdatesDAO updatesDao;
/** The registry of server-side update batch processors */
private final ServerProcessorRegistry registry;
/** The identifier of the current update cycle */
private final long tickId;
/**
* Initialise the various dependencies and set the identifier of the current cycle
*
* @param updatesDao
* the game updates database access interface
* @param registry
* the registry of server-side update batch processors
* @param tickId
* the identifier of the current update cycle
*/
GameUpdateTransaction( UpdatesDAO updatesDao , ServerProcessorRegistry registry , long tickId )
{
this.updatesDao = updatesDao;
this.registry = registry;
this.tickId = tickId;
}
/**
* Update batch processing transaction
*
* <p>
* Call the database's game update processing function, returning immediately if the function
* indicates that the cycle has been completed. Otherwise, execute a server-side processor if
* necessary.
*
* <p>
* If the database requests server-side processing but no processor is found, an
* {@link UnsupportedUpdateException} will be thrown.
*
* @return <code>true</code> if the current update cycle has been completed, <code>false</code>
* if more updates are needed.
*/
@Override
public Boolean doInTransaction( TransactionStatus status )
{
GameUpdateResult result = this.updatesDao.processUpdates( this.tickId );
String local = result.getLocalExecution( );
if ( result.isFinished( ) ) {
return true;
} else if ( local == null ) {
return false;
}
UpdateBatchProcessor processor = this.registry.getProcessorFor( local );
if ( processor == null ) {
throw new UnsupportedUpdateException( local );
}
processor.processBatch( this.tickId );
return false;
}
}

View file

@ -1,33 +0,0 @@
package com.deepclone.lw.beans.updates;
import com.deepclone.lw.interfaces.game.updates.UpdateBatchProcessor;
/**
* Server-side update processor registry
*
* <p>
* This interface allows server-side game update batch processors to be looked up depending on the
* type of the updates to process.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
interface ServerProcessorRegistry
{
/**
* Get a batch processor for some type of update
*
* @param type
* the type of updates to process, as stored in the <code>sys.update_types</code>
* database table
*
* @return <code>null</code> if no processor for the specified type has been registered, or the
* processor to use.
*/
public UpdateBatchProcessor getProcessorFor( String type );
}

View file

@ -1,68 +0,0 @@
package com.deepclone.lw.beans.updates;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import com.deepclone.lw.interfaces.game.updates.UpdateBatchProcessor;
/**
* Server-side update processor registry component
*
* <p>
* This component will look through registered Spring components for update processors, and use the
* results as the registry's contents.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class ServerProcessorRegistryBean
implements ServerProcessorRegistry , BeanPostProcessor
{
/** Known server-side update batch processors */
private final Map< String , UpdateBatchProcessor > processors = new HashMap< String , UpdateBatchProcessor >( );
/** Do nothing - we're not interested in uninitialised components */
@Override
public Object postProcessBeforeInitialization( Object bean , String beanName )
{
return bean;
}
/**
* If an initialised component implements the {@link UpdateBatchProcessor} interface, add it to
* the {@link #processors} map. A {@link BeanInitializationException} will be thrown if two
* components seem to process the same update type.
*/
@Override
public Object postProcessAfterInitialization( Object bean , String beanName )
throws BeansException
{
if ( bean instanceof UpdateBatchProcessor ) {
UpdateBatchProcessor processor = (UpdateBatchProcessor) bean;
String updType = processor.getUpdateType( );
if ( this.processors.containsKey( updType ) ) {
throw new BeanInitializationException( "Duplicate update processor for update type " + updType );
}
this.processors.put( updType , processor );
}
return bean;
}
/** Obtain the processor from the {@link #processors} map */
@Override
public UpdateBatchProcessor getProcessorFor( String type )
{
return this.processors.get( type );
}
}

View file

@ -1,29 +0,0 @@
package com.deepclone.lw.beans.updates;
/**
* Unsupported update exception
*
* <p>
* This exception is thrown by the {@link GameUpdateTransaction} when there is no server-side
* processor for some update type.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@SuppressWarnings( "serial" )
public class UnsupportedUpdateException
extends RuntimeException
{
/**
* Initialise the exception
*
* @param name
* the name of the update type for which no processor is registered.
*/
UnsupportedUpdateException( String name )
{
super( "No processor found for update type " + name );
}
}

View file

@ -1,69 +0,0 @@
package com.deepclone.lw.beans.updates;
import java.sql.Types;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
import com.deepclone.lw.sqld.sys.GameUpdateResult;
import com.deepclone.lw.utils.StoredProc;
/**
* Updates data access component
*
* <p>
* This component accesses the database procedures and views which constitute the game update
* system.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class UpdatesDAOBean
implements UpdatesDAO
{
/** Game update processor stored procedure */
private StoredProc process;
/**
* Dependency injector for the data source
*
* <p>
* When Spring injects the data source component, initialise the stored procedures used by the
* component.
*
* @param dataSource
* the data source component
*/
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.process = new StoredProc( dataSource , "sys" , "process_updates" ).addParameter( "tick_id" , Types.BIGINT )
.addOutput( "_has_more" , Types.BOOLEAN ).addOutput( "_process_externally" , Types.VARCHAR );
}
/**
* Execute the processor's stored procedure
*
* <p>
* This implementation simply runs the database's <code>sys.process_updates()</code> stored
* procedure, and converts the two values it returns into a {@link GameUpdateResult} instance.
*/
@Override
public GameUpdateResult processUpdates( long tickId )
{
Map< String , Object > m = this.process.execute( tickId );
if ( !(Boolean) m.get( "_has_more" ) ) {
return new GameUpdateResult( );
}
return new GameUpdateResult( (String) m.get( "_process_externally" ) );
}
}

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="gameUpdateDAO" class="com.deepclone.lw.beans.updates.UpdatesDAOBean" />
<bean id="gameUpdateProcessor" class="com.deepclone.lw.beans.updates.GameUpdateProcessorBean" />
<bean id="gameUpdateRegistry"
class="com.deepclone.lw.beans.updates.ServerProcessorRegistryBean" />
<bean id="gameUpdateTask" class="com.deepclone.lw.beans.updates.GameUpdateTaskBean" />
</beans>

View file

@ -1,74 +0,0 @@
package com.deepclone.lw.beans.user.player.game;
import org.springframework.beans.factory.annotation.Autowired;
import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
import com.deepclone.lw.beans.user.player.GameSubTypeBean;
import com.deepclone.lw.cmd.player.UpdateEmpireMiningSettingsCommand;
import com.deepclone.lw.interfaces.game.resources.ResourcesController;
import com.deepclone.lw.interfaces.session.ServerSession;
import com.deepclone.lw.session.Command;
import com.deepclone.lw.session.CommandResponse;
import com.deepclone.lw.session.NullResponse;
/**
* Command handler for empire mining settings updates
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class UpdateEmpireMiningSettingsCommandDelegateBean
implements AutowiredCommandDelegate
{
/** The resources controller */
private ResourcesController resourcesController;
/**
* Dependency injector that sets the resources controller
*
* @param resourcesController
* the resources controller
*/
@Autowired( required = true )
public void setResourcesController( ResourcesController resourcesController )
{
this.resourcesController = resourcesController;
}
/** This class handles {@link UpdateEmpireMiningSettingsCommand} instances */
@Override
public Class< ? extends Command > getType( )
{
return UpdateEmpireMiningSettingsCommand.class;
}
/** This class is enabled for the {@link GameSubTypeBean} session type */
@Override
public Class< ? extends SessionCommandHandler > getCommandHandler( )
{
return GameSubTypeBean.class;
}
/**
* If the account is not in vacation mode, update mining settings. Always return a
* {@link NullResponse}.
*/
@Override
public CommandResponse execute( ServerSession session , Command command )
{
if ( !session.get( "vacation" , Boolean.class ) ) {
int empireId = session.get( "empireId" , Integer.class );
this.resourcesController.updateEmpireSettings( empireId ,
( (UpdateEmpireMiningSettingsCommand) command ).getSettings( ) );
}
return new NullResponse( );
}
}

Some files were not shown because too many files have changed in this diff Show more