soc.game
Class SOCVersionedItem

java.lang.Object
  extended by soc.game.SOCVersionedItem
All Implemented Interfaces:
java.lang.Cloneable
Direct Known Subclasses:
SOCGameOption, SOCScenario

public abstract class SOCVersionedItem
extends java.lang.Object
implements java.lang.Cloneable

Information/objects which can change or have new ones with different versions. Items may have game-specific values, configurable at game creation.

A game may have none or some of the items (SOCGameOptions), or may use none or one of a type of item (SOCScenarios). See those subclasses for more details.

Version negotiation:
Each item has version information, because items can be added or changed with new versions of JSettlers. Since games run on the server, the server is authoritative about all items: If the client is newer, it must defer to the server's older set of known items. At client connect, the client compares its JSettlers version number to the server's, and asks for any changes to items if their versions differ.

Since:
2.0.00
Author:
Jeremy D Monin <jeremy@nand.net>

Field Summary
protected  java.lang.String desc
          Descriptive text for the item.
 boolean isKnown
          Is this item known or unknown at a given client or server version? Used in cross-version compatibility.
 java.lang.String key
          Item key name: Short alphanumeric name (uppercase, starting with a letter, '_' permitted).
 int lastModVersion
          Most recent game version in which this item changed, or if not modified, the version which added it.
 int minVersion
          Minimum game version supporting this item, or -1; same format as Version.versionNumber().
 
Constructor Summary
protected SOCVersionedItem(java.lang.String key)
          Create a new unknown item (== false).
  SOCVersionedItem(java.lang.String key, int minVers, int lastModVers, boolean isKnown, java.lang.String desc)
          Create a new versioned item.
 
Method Summary
static
<I extends SOCVersionedItem>
java.util.List<java.lang.String>
findUnknowns(java.util.Map<java.lang.String,I> items)
          Search this group of items and find any unknown ones (with ! isKnown).
 java.lang.String getDesc()
          Descriptive text for the item.
 int getMinVersion(java.util.Map<?,? extends SOCVersionedItem> items)
          Minimum game version supporting this item, given minVersion and the item's current value.
protected static
<I extends SOCVersionedItem>
java.util.List<I>
implItemsVersionCheck(int vers, boolean getAllForVersion, boolean checkValues, java.util.Map<java.lang.String,I> items)
          Get all items added or changed since version vers, or all items valid at vers, to implement itemsNewerThanVersion(int, boolean, Map) and itemsForVersion(int, Map).
static boolean isAlphanumericUpcaseAscii(java.lang.String s)
          Test whether a string's characters are all within the strict ranges 0-9, A-Z.
static
<I extends SOCVersionedItem>
java.util.List<I>
itemsForVersion(int vers, java.util.Map<java.lang.String,I> items)
          Get all items valid at version vers.
static int itemsMinimumVersion(java.util.Map<?,? extends SOCVersionedItem> items)
          Examine this set of items, calculating the minimum required version to support a game with these items.
static int itemsMinimumVersion(java.util.Map<?,? extends SOCVersionedItem> items, boolean calcMinVersionForUnchanged)
          Examine this set of items, calculating the minimum required version to support a game with these items.
static
<I extends SOCVersionedItem>
java.util.List<I>
itemsNewerThanVersion(int vers, boolean checkValues, java.util.Map<java.lang.String,I> items)
          Compare a set of items against the specified version.
 void setDesc(java.lang.String newDesc)
          Update this item's description text.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

key

public final java.lang.String key
Item key name: Short alphanumeric name (uppercase, starting with a letter, '_' permitted).


minVersion

public final int minVersion
Minimum game version supporting this item, or -1; same format as Version.versionNumber(). Public direct usage of this is discouraged; use itemsMinimumVersion(Map) or getMinVersion(Map) instead, because the current value of an item can change its minimum version. For example, a 5- or 6-player game will need a newer client than 4 players, but game option "PL"'s minVersion is -1, to allow 2- or 3-player games with any client.

See Also:
lastModVersion

lastModVersion

public final int lastModVersion
Most recent game version in which this item changed, or if not modified, the version which added it. changes would include different min/max values, updated description, etc. Same format as Version.versionNumber().

See Also:
minVersion

isKnown

public final boolean isKnown
Is this item known or unknown at a given client or server version? Used in cross-version compatibility.


desc

protected java.lang.String desc
Descriptive text for the item. Must not contain the network delimiter characters SOCMessage.sep_char or SOCMessage.sep2_char. See getDesc() for more info about this field.

Constructor Detail

SOCVersionedItem

protected SOCVersionedItem(java.lang.String key)
                    throws java.lang.IllegalArgumentException
Create a new unknown item (== false). Minimum version will be Integer.MAX_VALUE. Desc == key.

Parameters:
key - Alphanumeric 2-character code for this item; see isAlphanumericUpcaseAscii(String) for format.
Throws:
java.lang.IllegalArgumentException - if key length is > 3 or not alphanumeric, or if minVers or lastModVers is under 1000 but not -1

SOCVersionedItem

public SOCVersionedItem(java.lang.String key,
                        int minVers,
                        int lastModVers,
                        boolean isKnown,
                        java.lang.String desc)
                 throws java.lang.IllegalArgumentException
Create a new versioned item.

Parameters:
key - Alphanumeric code for this item; see isAlphanumericUpcaseAscii(String) for format.
minVers - Minimum client version where this item is included, or -1
lastModVers - Last-modified version for this item, or version which added it
isKnown - True if this item is known at the client or server version we're dealing with
desc - Descriptive brief text, to appear in the user interface. Desc must not contain SOCMessage.sep_char or SOCMessage.sep2_char, and must evaluate true from SOCMessage.isSingleLineAndSafe(String).
Throws:
java.lang.IllegalArgumentException - if key is not alphanumeric, or if desc contains SOCMessage.sep_char or SOCMessage.sep2_char, or if minVers or lastModVers is under 1000 but not -1
Method Detail

getDesc

public final java.lang.String getDesc()
Descriptive text for the item. Must not contain the network delimiter characters SOCMessage.sep_char or SOCMessage.sep2_char. If ! isKnown, will be key or an empty string.

Subclass SOCGameOption:
If option type is integer-valued (SOCGameOption.OTYPE_ENUM, SOCGameOption.OTYPE_INTBOOL, etc), may contain a placeholder '#' where the value is typed onscreen.

Before v2.0.00, desc was a public final field. This gave easy access without allowing changes to the description which might violate the formatting rules mentioned here. For i18n, v2.0.00 needed to be able to change the field contents, so getDesc() and setDesc(String) were added.

Returns:
the description; never null
Since:
2.0.00

setDesc

public void setDesc(java.lang.String newDesc)
             throws java.lang.IllegalArgumentException
Update this item's description text. See getDesc() for formatting rules and info.

Before v2.0.00, desc was a public final field. This gave easy access without allowing changes to the description which might violate the formatting rules. For i18n, v2.0.00 needed to be able to change the field contents, so getDesc() and setDesc(String) were added.

Parameters:
newDesc - Descriptive brief text, to appear in the user interface. Not null. Must not contain SOCMessage.sep_char or SOCMessage.sep2_char, and must evaluate true from SOCMessage.isSingleLineAndSafe(String).
Throws:
java.lang.IllegalArgumentException - if desc contains SOCMessage.sep_char or SOCMessage.sep2_char
Since:
2.0.00

getMinVersion

public int getMinVersion(java.util.Map<?,? extends SOCVersionedItem> items)
Minimum game version supporting this item, given minVersion and the item's current value. The current value of an item can change its minimum version. For example, a 5- or 6-player game will need a newer client than 4 players, but game option "PL"'s minVersion is -1, to allow 2- or 3-player games with any client.

Occasionally, an older client version supports a new item, but only by changing the value of some other items it recognizes. This method will calculate the minimum client version at which items are unchanged, if items != null.

Because this calculation is hardcoded here, the version returned may be too low when called at an older-version client. The server will let the client know if it's too old to join or create a game due to the requested game items.

This implementation just returns minVersion; override for more complex behavior. See SOCGameOption.getMinVersion(Map) for calculations done for game options ("PL", "SC", etc) based on their current value.

Parameters:
items - If null, return the minimum version supporting this item. Otherwise, the minimum version at which this item's value isn't changed (for compatibility) by the presence of other items.
Returns:
minimum version, or -1; same format as Version.versionNumber(). If items != null, the returned version will either be -1 or >= 1107 (the first version with game options) or >= 2000 (first version with scenarios), depending on the item subclass.
See Also:
itemsMinimumVersion(Map)

findUnknowns

public static <I extends SOCVersionedItem> java.util.List<java.lang.String> findUnknowns(java.util.Map<java.lang.String,I> items)
Search this group of items and find any unknown ones (with ! isKnown).

Parameters:
items - map of SOCVersionedItems
Returns:
List of unknown items' keys, or null if all are known

itemsMinimumVersion

public static int itemsMinimumVersion(java.util.Map<?,? extends SOCVersionedItem> items)
Examine this set of items, calculating the minimum required version to support a game with these items. Calls each item's getMinVersion(Map), where Map is null unless minCliVersionForUnchangedItems is true.

The current value of an item can change the item's minimum version. For example, game option "PL"'s minVersion is -1 for 2- to 4-player games with any client version, but a 5- or 6-player game will need client 1.1.08 or newer.

This calculation is done at the server when creating a new game. Although the client's version and classes (and thus its copy of itemsMinimumVersion) may be newer or older, and would give a different result if called, the server is authoritative for game items. Calls at the client to itemsMinimumVersion should keep this in mind, especially if a client's game option's lastModVersion is newer than the server.

Calls itemsMinimumVersion(items, false).

Parameters:
items - a set of items; not null
Returns:
the highest 'minimum version' among these items, or -1
See Also:
itemsMinimumVersion(Map, boolean), getMinVersion(Map)

itemsMinimumVersion

public static int itemsMinimumVersion(java.util.Map<?,? extends SOCVersionedItem> items,
                                      boolean calcMinVersionForUnchanged)
                               throws java.lang.NullPointerException
Examine this set of items, calculating the minimum required version to support a game with these items. Calls each item's getMinVersion(Map), where Map is null unless minCliVersionForUnchangedItems is true.

The current value of an item can change the item's minimum version. For example, game option "PL"'s minVersion is -1 for 2- to 4-player games with any client version, but a 5- or 6-player game will need client 1.1.08 or newer.

This calculation is done at the server when creating a new game. Although the client's version and classes (and thus its copy of itemsMinimumVersion) may be newer or older, and would give a different result if called, the server is authoritative for game items. Calls at the client to itemsMinimumVersion should keep this in mind, especially if a client's game option's lastModVersion is newer than the server.

Backwards-compatibility support: calcMinVersionForUnchanged parameter:
Occasionally, an older client version supports a new item, but only by changing the value of some other items it recognizes. If this parameter is true, this method will calculate the minimum client version at which the items are understood without backwards-compatibility changes to their values. (If all connected clients are this version or newer, that new game's item values can be broadcast to all clients without changes.) If calcMinVersionForUnchanged is true, the returned version may be higher than if false; older clients may support items only by changing some item values for compatibility.

Parameters:
items - a set of SOCVersionedItems; not null
calcMinVersionForUnchanged - If true, return the minimum version at which these options' values aren't changed (for compatibility) by the presence of new options.
Returns:
the highest 'minimum version' among these options, or -1. If calcMinVersionForUnchanged, the returned version will either be -1 or >= 1107 (the first version with game options).
Throws:
java.lang.NullPointerException - if items is null
See Also:
itemsMinimumVersion(Map), getMinVersion(Map)

itemsNewerThanVersion

public static <I extends SOCVersionedItem> java.util.List<I> itemsNewerThanVersion(int vers,
                                                                                   boolean checkValues,
                                                                                   java.util.Map<java.lang.String,I> items)
                                                                        throws java.lang.IllegalArgumentException
Compare a set of items against the specified version. Make a list of all which are new or changed since that version.

This method has 2 modes, because it's called for 2 different purposes:

See checkValues for method's behavior in each mode.

Parameters:
vers - Version to compare known items against
checkValues - Which mode: Check items' current values and minVersion, not their lastModVersion? An item's minimum version can increase based on its value; see getMinVersion(Map).
items - Set of items to check versions and current values
Returns:
List of the newer (added or changed) items, or null if all are known and unchanged since vers.
Note: May include items with minVersion > vers; for some item types the client may want to know about those.
Throws:
java.lang.NullPointerException - if items is null
java.lang.IllegalArgumentException
See Also:
itemsForVersion(int, Map)

itemsForVersion

public static <I extends SOCVersionedItem> java.util.List<I> itemsForVersion(int vers,
                                                                             java.util.Map<java.lang.String,I> items)
                                                                  throws java.lang.IllegalArgumentException
Get all items valid at version vers.

If vers from a client is newer than this version of SOCVersionedItem, will return all items known at this version, which may not include all of the newer version's items. Client game-item negotiation handles this by having the newer client send all its new (added or changed) item keynames to the older server to allow, adjust, or reject.

Parameters:
vers - Version to compare items against
items - Set of SOCVersionedItems to check versions
Returns:
List of all SOCVersionedItems valid at version vers, or null if none.
Throws:
java.lang.NullPointerException - if items is null
java.lang.IllegalArgumentException

implItemsVersionCheck

protected static <I extends SOCVersionedItem> java.util.List<I> implItemsVersionCheck(int vers,
                                                                                      boolean getAllForVersion,
                                                                                      boolean checkValues,
                                                                                      java.util.Map<java.lang.String,I> items)
                                                                           throws java.lang.IllegalArgumentException
Get all items added or changed since version vers, or all items valid at vers, to implement itemsNewerThanVersion(int, boolean, Map) and itemsForVersion(int, Map).

Parameters:
vers - Version to compare items against
getAllForVersion - True to get all valid items (itemsForVersion mode), false for newer added or changed items only (itemsNewerThanVersion modes). If true and vers is newer than this version of SOCVersionedItem, will return all items known at this version.
checkValues - If not getAllForVersion, which mode to run in: Check items' current values and minVersion, not their lastModVersion? An item's minimum version can increase based on its value; see getMinVersion(Map).
items - Set of SOCVersionedItems to check versions and current values; not null
Returns:
List of the requested SOCVersionedItems, or null if none match the conditions, at vers; see itemsNewerThanVersion and itemsForVersion for return details.
Note: If not getAllForVersion, may include items with minVersion > vers; for some item types the client may want to know about those.
Throws:
java.lang.IllegalArgumentException - if getAllForVersion && checkValues: Cannot combine these modes
java.lang.NullPointerException - if items is null

isAlphanumericUpcaseAscii

public static final boolean isAlphanumericUpcaseAscii(java.lang.String s)
Test whether a string's characters are all within the strict ranges 0-9, A-Z. The first character must be A-Z. Item name keys must start with a letter and contain only ASCII uppercase letters ('A' through 'Z') and digits ('0' through '9'), in order to normalize handling and network message formats.

Version 2.0.00 and newer allow '_' in game item and SOCGameOption names; please check minVersion vs '_' outside of this method, name keys with '_' can't be sent to older clients.

This method is placed in this class because versioned items (and their keys) are sometimes sent across a network.

Parameters:
s - string to test
Returns:
true if all characters are OK, false otherwise