|
From: Stefan F. <ste...@us...> - 2012-07-03 04:37:20
|
.classpath | 2
junit/lib/fest-2.0M5/fest-assert-core-2.0M5.jar |binary
junit/lib/fest-2.0M5/fest-util-1.2.0.jar |binary
junit/rails/game/state/AbstractItemImpl.java | 7 +
junit/rails/game/state/AbstractItemTest.java | 63 ++++++++++++++
junit/rails/game/state/ChangeStackTest.java | 7 -
junit/rails/game/state/ManagerImpl.java | 7 +
junit/rails/game/state/RootTest.java | 97 +++++++++++++++++++++
src/rails/common/parser/ComponentManager.java | 6 -
src/rails/common/parser/GameFileParser.java | 4
src/rails/game/Game.java | 2
src/rails/game/GameManager.java | 2
src/rails/game/state/AbstractItem.java | 16 ++-
src/rails/game/state/ArrayListChange.java | 4
src/rails/game/state/AutoChangeSet.java | 14 ---
src/rails/game/state/BooleanChange.java | 2
src/rails/game/state/Change.java | 6 -
src/rails/game/state/ChangeStack.java | 56 +++++-------
src/rails/game/state/Context.java | 10 --
src/rails/game/state/GenericStateChange.java | 2
src/rails/game/state/HashMapChange.java | 4
src/rails/game/state/HashSetChange.java | 2
src/rails/game/state/IntegerChange.java | 2
src/rails/game/state/Item.java | 2
src/rails/game/state/Manager.java | 66 ++++----------
src/rails/game/state/MultimapChange.java | 2
src/rails/game/state/Observable.java | 106 ++++++++++++++++++------
src/rails/game/state/PortfolioChange.java | 2
src/rails/game/state/Root.java | 45 ++++------
src/rails/game/state/State.java | 19 +---
src/rails/game/state/StateManager.java | 39 +++-----
src/rails/game/state/StringChange.java | 2
src/rails/game/state/WalletChange.java | 2
33 files changed, 390 insertions(+), 210 deletions(-)
New commits:
commit d776000fd05b1081b7ee4668fb91237553afe125
Author: Stefan Frey <ste...@we...>
Date: Tue Jul 3 06:36:39 2012 +0200
further refactoring of item mechanisms, added tests for root and item, added FEST assertions libraries
diff --git a/.classpath b/.classpath
index 724802d..7893f0d 100644
--- a/.classpath
+++ b/.classpath
@@ -17,5 +17,7 @@
<classpathentry kind="lib" path="src/lib/logback-1.0.4/logback-core-1.0.4.jar"/>
<classpathentry kind="lib" path="src/lib/sl4j-1.6.5/slf4j-api-1.6.5.jar"/>
<classpathentry kind="lib" path="src/lib/mockito-1.9.0/mockito-all-1.9.0.jar"/>
+ <classpathentry kind="lib" path="junit/lib/fest-2.0M5/fest-assert-core-2.0M5.jar"/>
+ <classpathentry kind="lib" path="junit/lib/fest-2.0M5/fest-util-1.2.0.jar"/>
<classpathentry kind="output" path="classes"/>
</classpath>
diff --git a/junit/lib/fest-2.0M5/fest-assert-core-2.0M5.jar b/junit/lib/fest-2.0M5/fest-assert-core-2.0M5.jar
new file mode 100644
index 0000000..e7c4b78
Binary files /dev/null and b/junit/lib/fest-2.0M5/fest-assert-core-2.0M5.jar differ
diff --git a/junit/lib/fest-2.0M5/fest-util-1.2.0.jar b/junit/lib/fest-2.0M5/fest-util-1.2.0.jar
new file mode 100644
index 0000000..560c705
Binary files /dev/null and b/junit/lib/fest-2.0M5/fest-util-1.2.0.jar differ
diff --git a/junit/rails/game/state/AbstractItemImpl.java b/junit/rails/game/state/AbstractItemImpl.java
new file mode 100644
index 0000000..3aec737
--- /dev/null
+++ b/junit/rails/game/state/AbstractItemImpl.java
@@ -0,0 +1,7 @@
+package rails.game.state;
+
+class AbstractItemImpl extends AbstractItem {
+ AbstractItemImpl(Item parent, String id) {
+ super(parent, id);
+ }
+}
diff --git a/junit/rails/game/state/AbstractItemTest.java b/junit/rails/game/state/AbstractItemTest.java
new file mode 100644
index 0000000..19c994e
--- /dev/null
+++ b/junit/rails/game/state/AbstractItemTest.java
@@ -0,0 +1,63 @@
+package rails.game.state;
+
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class AbstractItemTest {
+
+ private static final String MANAGER_ID = "manager";
+ private static final String ITEM_ID = "item";
+ private static final String ANOTHER_ID = "anotherItem";
+
+ private Root root;
+ private Manager manager;
+ private Item item;
+ private Item anotherItem;
+
+ @Before
+ public void setUp() {
+ root = Root.create();
+ manager = new ManagerImpl(root, MANAGER_ID);
+ item = new AbstractItemImpl(manager, ITEM_ID);
+ anotherItem = new AbstractItemImpl(item, ANOTHER_ID);
+ }
+
+ @Test
+ public void testGetId() {
+ assertEquals(item.getId(), ITEM_ID);
+ assertEquals(anotherItem.getId(), ANOTHER_ID);
+ }
+
+ @Test
+ public void testGetParent() {
+ assertSame(item.getParent(), manager);
+ assertSame(anotherItem.getParent(), item);
+ }
+
+ @Test
+ public void testGetContext() {
+ assertSame(item.getContext(), manager);
+ assertSame(anotherItem.getContext(), manager);
+ }
+
+ @Test
+ public void testGetRoot() {
+ assertSame(item.getRoot(), root);
+ assertSame(anotherItem.getRoot(), root);
+ }
+
+ @Test
+ public void testGetURI() {
+ assertEquals(item.getURI(), ITEM_ID);
+ assertEquals(anotherItem.getURI(), ITEM_ID + Item.SEP + ANOTHER_ID);
+ }
+
+ @Test
+ public void testGetFullURI() {
+ assertEquals(item.getFullURI(), Item.SEP + MANAGER_ID + Item.SEP + ITEM_ID);
+ assertEquals(anotherItem.getFullURI(), Item.SEP + MANAGER_ID+ Item.SEP + ITEM_ID + Item.SEP + ANOTHER_ID);
+ }
+
+}
diff --git a/junit/rails/game/state/ChangeStackTest.java b/junit/rails/game/state/ChangeStackTest.java
index 04dbb87..67a8618 100644
--- a/junit/rails/game/state/ChangeStackTest.java
+++ b/junit/rails/game/state/ChangeStackTest.java
@@ -16,13 +16,6 @@ public class ChangeStackTest {
assertNotNull(stack);
}
- @Test
- public void testEnable() {
- ChangeStack stack = ChangeStack.create(sm);
- assertFalse(stack.isEnabled());
- stack.enable();
- assertTrue(stack.isEnabled());
- }
@Test
public void testIsEnabled() {
diff --git a/junit/rails/game/state/ManagerImpl.java b/junit/rails/game/state/ManagerImpl.java
new file mode 100644
index 0000000..a6fdf00
--- /dev/null
+++ b/junit/rails/game/state/ManagerImpl.java
@@ -0,0 +1,7 @@
+package rails.game.state;
+
+class ManagerImpl extends Manager {
+ ManagerImpl(Item parent, String id) {
+ super(parent, id);
+ }
+}
diff --git a/junit/rails/game/state/RootTest.java b/junit/rails/game/state/RootTest.java
new file mode 100644
index 0000000..97b4482
--- /dev/null
+++ b/junit/rails/game/state/RootTest.java
@@ -0,0 +1,97 @@
+package rails.game.state;
+
+import static org.junit.Assert.*;
+import static org.fest.assertions.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class RootTest {
+
+ private static final String MANAGER_ID = "manager";
+ private static final String ITEM_ID = "item";
+ private static final String ANOTHER_ID = "anotherItem";
+
+ private Root root;
+ private Manager manager;
+ private Item item;
+ private Item anotherItem;
+
+ @Before
+ public void setUp() {
+ root = Root.create();
+ manager = new ManagerImpl(root, MANAGER_ID);
+ item = new AbstractItemImpl(root, ITEM_ID);
+ anotherItem = new AbstractItemImpl(manager, ANOTHER_ID);
+ }
+
+ @Test
+ public void testGetStateManager() {
+ assertThat(root.getStateManager()).isInstanceOf(StateManager.class);
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testGetParent() {
+ root.getParent();
+ }
+
+ @Test
+ public void testGetId() {
+ assertEquals(root.getId(), Root.ID);
+ }
+
+ @Test
+ public void testGetContext() {
+ assertSame(root.getContext(), root);
+ }
+
+ @Test
+ public void testGetRoot() {
+ assertSame(root.getRoot(), root);
+ }
+
+ @Test
+ public void testGetURI() {
+ assertSame(root.getURI(), Root.ID);
+ }
+
+ @Test
+ public void testGetFullURI() {
+ assertSame(root.getFullURI(), Root.ID);
+ }
+
+ @Test
+ public void testLocate() {
+ assertSame(root.locate(item.getFullURI()), item);
+ assertSame(root.locate(anotherItem.getFullURI()), anotherItem);
+ }
+
+ @Test
+ public void testLocateFail() {
+ root.removeItem(item);
+ assertNull(root.locate(item.getFullURI()));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testAddItemFail() {
+ root.addItem(item);
+ }
+
+ public void testAddItemSuccess() {
+ root.removeItem(item);
+ root.addItem(item);
+ assertSame(root.locate(item.getFullURI()), item);
+ }
+
+ public void testRemoveItemSuccess() {
+ root.removeItem(item);
+ root.locate(item.getFullURI());
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testRemoveItemFail() {
+ root.removeItem(item);
+ root.removeItem(item);
+ }
+
+}
diff --git a/src/rails/common/parser/ComponentManager.java b/src/rails/common/parser/ComponentManager.java
index 3e0d57f..daa7f30 100644
--- a/src/rails/common/parser/ComponentManager.java
+++ b/src/rails/common/parser/ComponentManager.java
@@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory;
import rails.common.LocalText;
import rails.common.parser.XMLTags;
-import rails.game.state.Manager;
+import rails.game.state.Context;
/**
* ComponentManage - an implementation of ComponentManagerI, which handles the
@@ -28,7 +28,7 @@ public class ComponentManager {
private Map<String, ConfigurableComponent> mComponentMap =
new HashMap<String, ConfigurableComponent>();
- public ComponentManager(Manager context, String gameName, Tag tag, Map<String, String> gameOptions)
+ public ComponentManager(Context context, String gameName, Tag tag, Map<String, String> gameOptions)
throws ConfigurationException {
this.gameName = gameName;
@@ -41,7 +41,7 @@ public class ComponentManager {
}
}
- private void configureComponent(Manager context, Tag componentTag)
+ private void configureComponent(Context context, Tag componentTag)
throws ConfigurationException {
// Extract the attributes of the Component
diff --git a/src/rails/common/parser/GameFileParser.java b/src/rails/common/parser/GameFileParser.java
index f4ebe84..c1b6fd5 100644
--- a/src/rails/common/parser/GameFileParser.java
+++ b/src/rails/common/parser/GameFileParser.java
@@ -15,7 +15,7 @@ import rails.game.PlayerManager;
import rails.game.StockMarket;
import rails.game.TileManager;
import rails.game.TrainManager;
-import rails.game.state.Manager;
+import rails.game.state.Root;
public class GameFileParser extends XMLParser {
private static String GAME_XML_FILE = "Game.xml";
@@ -34,7 +34,7 @@ public class GameFileParser extends XMLParser {
private RevenueManager revenueManager;
private Bank bank;
- public GameFileParser(Manager context, String name, Map<String, String> gameOptions) {
+ public GameFileParser(Root context, String name, Map<String, String> gameOptions) {
directories.add("data/" + name);
diff --git a/src/rails/game/Game.java b/src/rails/game/Game.java
index b71533c..3140cb0 100644
--- a/src/rails/game/Game.java
+++ b/src/rails/game/Game.java
@@ -77,7 +77,7 @@ public class Game {
public boolean setup() {
// first define root GameContext to be able to define states
- Root root = Root.create("states");
+ Root root = Root.create();
GameFileParser gfp = new GameFileParser(root, name, gameOptions);
playerManager = gfp.getPlayerManager();
diff --git a/src/rails/game/GameManager.java b/src/rails/game/GameManager.java
index 9fa593e..db9d978 100644
--- a/src/rails/game/GameManager.java
+++ b/src/rails/game/GameManager.java
@@ -567,7 +567,7 @@ public class GameManager extends AbstractItem implements ConfigurableComponent,
}
// Initialisation is complete. Undoability starts here.
- changeStack.enable();
+ // changeStack.enable();
}
private void setGuiParameters () {
diff --git a/src/rails/game/state/AbstractItem.java b/src/rails/game/state/AbstractItem.java
index e76ec25..531724f 100644
--- a/src/rails/game/state/AbstractItem.java
+++ b/src/rails/game/state/AbstractItem.java
@@ -9,6 +9,7 @@ public abstract class AbstractItem implements Item {
private final String id;
private final Item parent;
+ private final Context context;
protected AbstractItem(Item parent, String id){
checkNotNull(parent, "Parent cannot be null");
@@ -18,9 +19,10 @@ public abstract class AbstractItem implements Item {
// defined standard fields
this.parent = parent;
this.id = id;
+ context = parent.getContext();
// add item to context
- parent.getContext().addItem(this);
+ context.addItem(this);
}
public String getId() {
@@ -32,12 +34,12 @@ public abstract class AbstractItem implements Item {
}
public Context getContext() {
- if (parent instanceof Manager) {
- return (Manager)parent;
- } else {
- // recursive definition
- return parent.getContext();
- }
+ return context;
+ }
+
+ public Root getRoot() {
+ // forward it to the context
+ return context.getRoot();
}
public String getURI() {
diff --git a/src/rails/game/state/ArrayListChange.java b/src/rails/game/state/ArrayListChange.java
index 4e28257..f9016c1 100644
--- a/src/rails/game/state/ArrayListChange.java
+++ b/src/rails/game/state/ArrayListChange.java
@@ -21,22 +21,22 @@ final class ArrayListChange<E> extends Change {
* Add object at the specified index
*/
ArrayListChange(ArrayListState<E> state, E object, int index) {
- super(state);
this.state = state;
this.object = object;
this.index = index;
this.addToList = true;
+ super.init(state);
}
/**
* Remove object at the specified index
*/
ArrayListChange(ArrayListState<E> state, int index) {
- super(state);
this.state = state;
this.object = state.get(index);
this.index = index;
this.addToList = false;
+ super.init(state);
}
@Override
diff --git a/src/rails/game/state/AutoChangeSet.java b/src/rails/game/state/AutoChangeSet.java
index b1e8de8..11fe5a3 100644
--- a/src/rails/game/state/AutoChangeSet.java
+++ b/src/rails/game/state/AutoChangeSet.java
@@ -3,20 +3,12 @@ package rails.game.state;
import rails.game.Player;
/**
- * AutoChangeSets are linked to previous ActionChangeSets
- * @author freystef
+ * AutoChangeSets are ChangeSets that belong to no action directly
*/
final class AutoChangeSet extends ChangeSet {
- private final ActionChangeSet previous;
- AutoChangeSet(ActionChangeSet previous) {
- this.previous = previous;
- }
-
- ActionChangeSet getPrevious() {
- return previous;
- }
+ AutoChangeSet() {}
@Override
boolean isUndoableByPlayer(Player player) {
@@ -25,7 +17,7 @@ final class AutoChangeSet extends ChangeSet {
@Override
public String toString() {
- return "AutoChangeSet linked to action " + previous.getAction();
+ return "AutoChangeSet";
}
}
diff --git a/src/rails/game/state/BooleanChange.java b/src/rails/game/state/BooleanChange.java
index b899756..be51279 100644
--- a/src/rails/game/state/BooleanChange.java
+++ b/src/rails/game/state/BooleanChange.java
@@ -12,10 +12,10 @@ final class BooleanChange extends Change {
private final boolean oldValue;
BooleanChange(BooleanState state, boolean newValue) {
- super(state);
this.state = state;
this.newValue = newValue;
this.oldValue = state.booleanValue();
+ super.init(state);
}
@Override
diff --git a/src/rails/game/state/Change.java b/src/rails/game/state/Change.java
index ec1d12a..8fd74c2 100644
--- a/src/rails/game/state/Change.java
+++ b/src/rails/game/state/Change.java
@@ -3,13 +3,11 @@ package rails.game.state;
* Base Class for all Change Objects
*
* Replaces previous move interface
- *
- * @author freystef
*/
abstract class Change {
- Change(State state){
- state.getStateManager().addChangeToStack(this);
+ protected void init(State state){
+ state.getRoot().getStateManager().addChangeToStack(this);
}
abstract void execute();
diff --git a/src/rails/game/state/ChangeStack.java b/src/rails/game/state/ChangeStack.java
index 3090ae0..7b7e52f 100644
--- a/src/rails/game/state/ChangeStack.java
+++ b/src/rails/game/state/ChangeStack.java
@@ -9,50 +9,32 @@ import rails.game.Player;
import rails.game.ReportBuffer;
import rails.game.action.PossibleAction;
-public class ChangeStack extends AbstractItem {
+public class ChangeStack {
protected static Logger log =
LoggerFactory.getLogger(ChangeStack.class.getPackage().getName());
private final LinkedList<ChangeSet> stack = new LinkedList<ChangeSet>();
-
- private boolean enabled = false;
+ private final StateManager stateManager;
- protected ChangeStack(Item parent, String id){
- super(parent, id);
+ private ChangeStack(StateManager parent) {
+ stateManager = parent;
}
/**
* @param parent restricted to StateManager
- * ID set to class name
*/
public static ChangeStack create(StateManager parent) {
- return new ChangeStack(parent , ChangeStack.class.getSimpleName());
- }
-
- /**
- * Start making moves undoable. Will be called once, after all
- * initialisations are complete.
- */
- public void enable() {
- enabled = true;
- }
-
- public boolean isEnabled() {
- return enabled;
+ ChangeStack changeStack = new ChangeStack(parent);
+ changeStack.initAutoChangeSet();
+ return changeStack;
}
- private void checkEnabled() {
- if (!enabled) throw new IllegalStateException("ChangeStack is not enabled");
- }
-
/**
* Returns a valid ChangeSet that is current for the ChangeStack
* If the ChangeStack is not enabled or empty a IllegalStateExcpetion is thrown
* @return the current changeSet
*/
public ChangeSet getAvailableChangeSet() {
- // check preconditions
- checkEnabled();
if (stack.isEmpty()) throw new IllegalStateException("No ChangeSet on ChangeStack");
// return the last on the
@@ -77,6 +59,23 @@ public class ChangeStack extends AbstractItem {
}
return changeSet;
}
+
+ /**
+ * Creates new AutoChangeSet
+ */
+ public AutoChangeSet initAutoChangeSet() {
+ if (stack.peekLast() != null && !stack.peekLast().isClosed())
+ throw new IllegalStateException("Current ChangeSet not closed yet");
+
+ // create new ChangeSet
+ AutoChangeSet changeSet = new AutoChangeSet();
+
+ stack.offerLast(changeSet);
+ log.debug(">>> Start AutoChangeSet " + changeSet + " at index=" + stack.size() + " <<<");
+
+ return changeSet;
+ }
+
/**
* Creates new ActionChangeSet
@@ -85,9 +84,6 @@ public class ChangeStack extends AbstractItem {
* @return the new current ChangeSet
*/
public ActionChangeSet start(Player player, PossibleAction action) {
-
- // check preconditions
- checkEnabled();
if (stack.peekLast() != null && !stack.peekLast().isClosed())
throw new IllegalStateException("Current ChangeSet not closed yet");
@@ -159,11 +155,11 @@ public class ChangeStack extends AbstractItem {
}
public boolean isUndoableByManager() {
- return enabled && stack.size() != 0;
+ return stack.size() != 0;
}
public boolean isOpen() {
- return enabled && stack.size() != 0 && !getAvailableChangeSet().isClosed();
+ return stack.size() != 0 && !getAvailableChangeSet().isClosed();
}
// TODO: What is correct?
diff --git a/src/rails/game/state/Context.java b/src/rails/game/state/Context.java
index 487e1e3..9d5520c 100644
--- a/src/rails/game/state/Context.java
+++ b/src/rails/game/state/Context.java
@@ -2,14 +2,12 @@ package rails.game.state;
/**
* A context describe a service that allows to locate items
*/
-public interface Context extends Item {
+public abstract class Context implements Item {
- public Item localize(String uri);
+ public abstract Item locate(String uri);
- public void addItem(Item item);
+ abstract void addItem(Item item);
- public void removeItem(Item item);
-
- public Root getRoot();
+ abstract void removeItem(Item item);
}
diff --git a/src/rails/game/state/GenericStateChange.java b/src/rails/game/state/GenericStateChange.java
index 6922321..076f731 100644
--- a/src/rails/game/state/GenericStateChange.java
+++ b/src/rails/game/state/GenericStateChange.java
@@ -6,10 +6,10 @@ final class GenericStateChange<E> extends Change {
final private E previous, next;
public GenericStateChange(GenericState<E> state, E object) {
- super(state);
this.state = state;
previous = state.get();
next = object;
+ super.init(state);
}
@Override
diff --git a/src/rails/game/state/HashMapChange.java b/src/rails/game/state/HashMapChange.java
index a3572bf..ac89844 100644
--- a/src/rails/game/state/HashMapChange.java
+++ b/src/rails/game/state/HashMapChange.java
@@ -16,26 +16,26 @@ final class HashMapChange<K,V> extends Change {
* Put element into map
*/
HashMapChange(HashMapState<K,V> state, K key, V value) {
- super(state);
this.state = state;
this.key = key;
newValue = value;
remove = false;
oldValue = state.get(key);
existed = state.containsKey(key);
+ super.init(state);
}
/**
* Remove element from map
*/
HashMapChange(HashMapState<K,V> state, K key) {
- super(state);
this.state = state;
this.key = key;
newValue = null;
remove = true;
oldValue = state.get(key);
existed = true;
+ super.init(state);
}
@Override
diff --git a/src/rails/game/state/HashSetChange.java b/src/rails/game/state/HashSetChange.java
index 31f260f..eaec2e4 100644
--- a/src/rails/game/state/HashSetChange.java
+++ b/src/rails/game/state/HashSetChange.java
@@ -12,10 +12,10 @@ final class HashSetChange<E> extends Change {
* Add/Remove element to/from the set
*/
HashSetChange(HashSetState<E> state, E element, boolean addToSet){
- super(state);
this.state = state;
this.element = element;
this.addToSet = addToSet;
+ super.init(state);
}
@Override
diff --git a/src/rails/game/state/IntegerChange.java b/src/rails/game/state/IntegerChange.java
index 55a56b3..0375d93 100644
--- a/src/rails/game/state/IntegerChange.java
+++ b/src/rails/game/state/IntegerChange.java
@@ -10,10 +10,10 @@ final class IntegerChange extends Change {
private final int oldValue;
IntegerChange(IntegerState state, int newValue) {
- super(state);
this.state = state;
this.newValue = newValue;
this.oldValue = state.value();
+ super.init(state);
}
@Override
diff --git a/src/rails/game/state/Item.java b/src/rails/game/state/Item.java
index be16c84..d4a8877 100644
--- a/src/rails/game/state/Item.java
+++ b/src/rails/game/state/Item.java
@@ -21,6 +21,8 @@ public interface Item {
Item getParent();
Context getContext();
+
+ Root getRoot();
/**
* @return a string which allows to identify the item in the Context
diff --git a/src/rails/game/state/Manager.java b/src/rails/game/state/Manager.java
index 11d5a3b..2d995c5 100644
--- a/src/rails/game/state/Manager.java
+++ b/src/rails/game/state/Manager.java
@@ -4,36 +4,34 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
- * A Manager is an abstract implementation of a Context
+ * A Manager is a baseline implementation of a Context
*/
-public abstract class Manager implements Context {
+public abstract class Manager extends Context {
- // standard item fields
+ // item fields
private final String id;
private final Item parent;
-
- protected final Root root;
-
- // storage of items
- protected final HashMapState<String, Item> items = HashMapState.create(this, "items");
+ // context fields
+ private final Root root;
+ private final String fullURI;
protected Manager(Item parent, String id) {
checkNotNull(id, "Id cannot be null");
this.id = id;
- if (this instanceof Root) {
- this.parent = null;
- this.root = null;
- return;
- }
-
// check arguments, parent can only be null for Root
checkNotNull(parent, "Parent cannot be null");
this.parent = parent;
+ // URI defined recursively
+ fullURI = parent.getFullURI() + Item.SEP + id;
+
// find root and add context there
root = parent.getContext().getRoot();
- root.addItem(this);
+ // add to root, except for StateManager, this is delayed
+ if (!(this instanceof StateManager)) {
+ root.addItem(this);
+ }
}
public String getId() {
@@ -49,52 +47,30 @@ public abstract class Manager implements Context {
}
public String getURI() {
- if (parent instanceof Manager) {
- return id;
- } else {
- // recursive definition
- return parent.getURI() + Item.SEP + id;
- }
+ return "";
}
public String getFullURI() {
- // recursive definition
- return parent.getFullURI() + Item.SEP + id;
+ return fullURI;
}
// Context methods
- public Item localize(String uri) {
- // either item can be found in the map
- if (items.containsKey(uri)) {
- return items.get(uri);
- } else {
- // otherwise search in root
- return root.localize(uri);
- }
+ public Item locate(String uri) {
+ return root.locate(fullURI + Item.SEP + uri);
}
- public void addItem(Item item) {
+ void addItem(Item item) {
// check if this context is the containing one
checkArgument(item.getContext() == this, "Context is not the container of the item to add");
- // check if it already exists
- checkArgument(items.containsKey(item.getURI()), "Context already contains item with identical URI");
-
- // all preconditions ok => add item
- items.put(item.getURI(), item);
// add item to root
root.addItem(item);
- }
+ }
- public void removeItem(Item item) {
+ void removeItem(Item item) {
// check if this context is the containing one
checkArgument(item.getContext() == this, "Context is not the container of the item to add");
- // check if it is stored
- checkArgument(!items.containsKey(item.getURI()), "Context does not contain item with that URI");
-
- // all preconditions ok => remove item
- items.remove(item.getURI());
-
+
// remove item from root
root.removeItem(item);
}
diff --git a/src/rails/game/state/MultimapChange.java b/src/rails/game/state/MultimapChange.java
index dedca99..115465e 100644
--- a/src/rails/game/state/MultimapChange.java
+++ b/src/rails/game/state/MultimapChange.java
@@ -7,11 +7,11 @@ final class MultimapChange<K,V> extends Change {
final private boolean addToMap;
MultimapChange(MultimapState<K,V> state, K key, V value, boolean addToMap) {
- super(state);
this.state = state;
this.key = key;
this.value = value;
this.addToMap = addToMap;
+ super.init(state);
}
@Override
diff --git a/src/rails/game/state/Observable.java b/src/rails/game/state/Observable.java
index bc339cb..3272391 100644
--- a/src/rails/game/state/Observable.java
+++ b/src/rails/game/state/Observable.java
@@ -1,68 +1,128 @@
package rails.game.state;
-import com.google.common.collect.ImmutableSet;
-
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import com.google.common.collect.ImmutableSet;
/**
* Requirement:
* The observable object has to call each observer per update() if the object has changed.
- *
- * @author freystef
- *
*/
-public abstract class Observable extends AbstractItem {
+public abstract class Observable implements Item {
- // stores observers and models
- private HashSetState<Observer> observers = null; // lazy initialization
- private HashSetState<Model> models = null; // lazy initialization
+ // fields for Item implementation
+ private final String id;
+ private final Item parent;
+ private final Context context;
+ // stores observers and models if observable
+ // those are unobservable states themselves
+ private final HashSetState<Observer> observers;
+ private final HashSetState<Model> models;
+
+ /**
+ * @param parent parent node in item hierarchy (cannot be null)
+ * @param id id of the observable
+ * If id is null it creates an "unobservable" observable
+ * This is required for the creation of states that are themselves stateless
+ */
+
protected Observab...
[truncated message content] |