From dd69489de4248656e47badffe62e99f791d4f2e3 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Wed, 5 Dec 2001 03:38:10 +0000 Subject: [PATCH] More scene and spot scene refactoring. Got parsers working for those in the new new style (or was that the new new new style). git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@739 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../spot/client/DisplaySpotSceneImpl.java | 68 +++++++++-- .../whirled/spot/data/Location.java | 14 +-- .../threerings/whirled/spot/data/Portal.java | 17 +-- .../whirled/spot/tools/EditableLocation.java | 69 ----------- .../whirled/spot/tools/EditablePortal.java | 52 ++------ .../whirled/spot/tools/EditableSpotScene.java | 6 +- .../spot/tools/EditableSpotSceneImpl.java | 111 ++++++++---------- .../spot/tools/EditableSpotSceneModel.java | 60 +++++++++- .../spot/tools/xml/SpotSceneParser.java | 59 ++++++++++ .../spot/tools/xml/SpotSceneRuleSet.java | 50 ++++---- .../whirled/tools/EditableScene.java | 19 ++- .../whirled/tools/EditableSceneImpl.java | 27 ++++- .../whirled/tools/EditableSceneModel.java | 58 ++++++++- .../whirled/tools/xml/SceneParser.java | 58 +++++++++ .../whirled/tools/xml/SceneRuleSet.java | 36 +++--- tests/rsrc/whirled/spot/tools/xml/scene.xml | 12 ++ tests/rsrc/whirled/tools/xml/scene.xml | 8 ++ .../spot/tools/xml/SpotSceneParserTest.java | 47 ++++++++ .../whirled/tools/xml/SceneParserTest.java | 47 ++++++++ 19 files changed, 544 insertions(+), 274 deletions(-) delete mode 100644 src/java/com/threerings/whirled/spot/tools/EditableLocation.java create mode 100644 src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParser.java create mode 100644 src/java/com/threerings/whirled/tools/xml/SceneParser.java create mode 100644 tests/rsrc/whirled/spot/tools/xml/scene.xml create mode 100644 tests/rsrc/whirled/tools/xml/scene.xml create mode 100644 tests/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParserTest.java create mode 100644 tests/src/java/com/threerings/whirled/tools/xml/SceneParserTest.java diff --git a/src/java/com/threerings/whirled/spot/client/DisplaySpotSceneImpl.java b/src/java/com/threerings/whirled/spot/client/DisplaySpotSceneImpl.java index 14958e8e4..6bd73ddc9 100644 --- a/src/java/com/threerings/whirled/spot/client/DisplaySpotSceneImpl.java +++ b/src/java/com/threerings/whirled/spot/client/DisplaySpotSceneImpl.java @@ -1,5 +1,5 @@ // -// $Id: DisplaySpotSceneImpl.java,v 1.2 2001/11/29 00:16:11 mdb Exp $ +// $Id: DisplaySpotSceneImpl.java,v 1.3 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.spot.client; @@ -43,18 +43,14 @@ public class DisplaySpotSceneImpl extends DisplaySceneImpl if (model.locationIds[i] == pid) { // add this portal to the portals array - _portals[pidx] = new Portal( - pid, model.locationX[i], model.locationY[i], - model.locationOrients[i], model.neighborIds[pidx], - model.targetLocIds[pidx]); + _portals[pidx] = createPortal(); + populatePortal(model, _portals[pidx], i, pidx); loc = _portals[pidx]; pidx++; } else { - loc = new Location( - model.locationIds[i], model.locationX[i], - model.locationY[i], model.locationOrients[i], - model.locationClusters[i]); + loc = createLocation(); + populateLocation(model, loc, i); } // everything goes into the locations array @@ -62,6 +58,60 @@ public class DisplaySpotSceneImpl extends DisplaySceneImpl } } + /** + * Returns a new location instance. + */ + protected Location createLocation () + { + return new Location(); + } + + /** + * Populates a location instance with the specified index, using + * information from the model. + * + * @param model the scene model. + * @param loc the location instance to populate. + * @param lidx the location index in the model arrays. + */ + protected void populateLocation ( + SpotSceneModel model, Location loc, int lidx) + { + loc.locationId = model.locationIds[lidx]; + loc.x = model.locationX[lidx]; + loc.y = model.locationY[lidx]; + loc.orientation = model.locationOrients[lidx]; + loc.clusterIndex = model.locationClusters[lidx]; + } + + /** + * Returns a new portal instance. + */ + protected Portal createPortal () + { + return new Portal(); + } + + /** + * Populates a portal instance with the specified index, using + * information from the model. + * + * @param model the scene model. + * @param port the portal to populate. + * @param lidx the location index in the model arrays. + * @param pidx the portal index in the model arrays. + */ + protected void populatePortal ( + SpotSceneModel model, Portal port, int lidx, int pidx) + { + // populate the location fields + populateLocation(model, port, lidx); + + // populate the portal-specific fields + port.targetSceneId = model.neighborIds[pidx]; + port.targetLocId = model.targetLocIds[pidx]; + } + // documentation inherited public int getDefaultEntranceId () { diff --git a/src/java/com/threerings/whirled/spot/data/Location.java b/src/java/com/threerings/whirled/spot/data/Location.java index 0d37a378a..e3b24f809 100644 --- a/src/java/com/threerings/whirled/spot/data/Location.java +++ b/src/java/com/threerings/whirled/spot/data/Location.java @@ -1,5 +1,5 @@ // -// $Id: Location.java,v 1.2 2001/12/03 19:40:11 mdb Exp $ +// $Id: Location.java,v 1.3 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.spot.data; @@ -29,18 +29,6 @@ public class Location * no cluster. */ public int clusterIndex; - /** - * Constructs a location with the supplied values. - */ - public Location (int id, int x, int y, int orientation, int clusterIndex) - { - this.locationId = id; - this.x = x; - this.y = y; - this.orientation = orientation; - this.clusterIndex = clusterIndex; - } - /** * Location equality is determined by location id. */ diff --git a/src/java/com/threerings/whirled/spot/data/Portal.java b/src/java/com/threerings/whirled/spot/data/Portal.java index 2e88a4833..178b29442 100644 --- a/src/java/com/threerings/whirled/spot/data/Portal.java +++ b/src/java/com/threerings/whirled/spot/data/Portal.java @@ -1,5 +1,5 @@ // -// $Id: Portal.java,v 1.3 2001/12/04 22:34:04 mdb Exp $ +// $Id: Portal.java,v 1.4 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.spot.data; @@ -25,24 +25,13 @@ public class Portal extends Location /** The location identifier of the location at which a body will enter * the target scene when they "use" this portal. */ - public int targetLocationId; - - /** - * Constructs a portal with the supplied values. - */ - public Portal (int id, int x, int y, int orientation, - int targetSceneId, int targetLocationId) - { - super(id, x, y, orientation, -1); - this.targetSceneId = targetSceneId; - this.targetLocationId = targetLocationId; - } + public int targetLocId; // documentation inherited protected void toString (StringBuffer buf) { super.toString(buf); buf.append(", targetScene=").append(targetSceneId); - buf.append(", targetLoc=").append(targetLocationId); + buf.append(", targetLoc=").append(targetLocId); } } diff --git a/src/java/com/threerings/whirled/spot/tools/EditableLocation.java b/src/java/com/threerings/whirled/spot/tools/EditableLocation.java deleted file mode 100644 index 05d69ad20..000000000 --- a/src/java/com/threerings/whirled/spot/tools/EditableLocation.java +++ /dev/null @@ -1,69 +0,0 @@ -// -// $Id: EditableLocation.java,v 1.1 2001/12/04 22:34:04 mdb Exp $ - -package com.threerings.whirled.tools.spot; - -import com.threerings.whirled.spot.data.Location; - -/** - * An editable location contains a name as well as the standard location - * information. - */ -public class EditableLocation -{ - /** The location whose data we extend. (My kingdom for multiple - * inheritance.) */ - public Location location; - - /** The human-readable name of this location. */ - public String name; - - /** - * Constructs an editable location. A location delegate will be - * created with the supplied basic location information. - */ - public EditableLocation (int id, int x, int y, int orientation, - int clusterIndex, String name) - { - this(new Location(id, x, y, orientation, clusterIndex), name); - } - - /** - * Constructs an editable location with the supplied location - * delegate. - */ - public EditableLocation (Location source, String name) - { - location = source; - this.name = name; - } - - /** - * Generates a string representation of this instance. - */ - public String toString () - { - StringBuffer buf = new StringBuffer("["); - delegatesToString(buf); - toString(buf); - return buf.append("]").toString(); - } - - /** - * Generates a string representation of this instance's delegates into - * the supplied string buffer. - */ - protected void delegatesToString (StringBuffer buf) - { - buf.append(location); - } - - /** - * Generates a string representation of this instance's members into - * the supplied string buffer. - */ - protected void toString (StringBuffer buf) - { - buf.append(", name=").append(name); - } -} diff --git a/src/java/com/threerings/whirled/spot/tools/EditablePortal.java b/src/java/com/threerings/whirled/spot/tools/EditablePortal.java index e6c8f1ec4..4c78371af 100644 --- a/src/java/com/threerings/whirled/spot/tools/EditablePortal.java +++ b/src/java/com/threerings/whirled/spot/tools/EditablePortal.java @@ -1,65 +1,33 @@ // -// $Id: EditablePortal.java,v 1.1 2001/12/04 22:34:04 mdb Exp $ +// $Id: EditablePortal.java,v 1.2 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.tools.spot; import com.threerings.whirled.spot.data.Portal; /** - * An editable portal contains a name as well as the standard portal - * information. + * An editable portal extends the standard portal with information needed + * by the loader and editor. */ -public class EditablePortal extends EditableLocation +public class EditablePortal extends Portal { - /** The portal whose data we extend. (My kingdom for multiple - * inheritance.) */ - public Portal portal; + /** The human-readable name of this portal. */ + public String name; /** The human-readable name of the scene to which this portal * links. */ public String targetSceneName; - /** The human-readable name of the location to which this portal links + /** The human-readable name of the portal to which this portal links * in its target scene. */ - public String targetLocName; - - /** - * Constructs an editable portal. A portal delegate will be created - * with the supplied basic portal information. - */ - public EditablePortal ( - int id, int x, int y, int orientation, int targetSceneId, - int targetLocId, String name, String targetSceneName, - String targetLocName) - { - this(new Portal(id, x, y, orientation, targetSceneId, targetLocId), - name, targetSceneName, targetLocName); - } - - /** - * Constructs an editable portal with the specified portal delegate - * and specified extended information. - */ - public EditablePortal (Portal source, String name, - String targetSceneName, String targetLocName) - { - super(source, name); - portal = source; - this.targetSceneName = targetSceneName; - this.targetLocName = targetLocName; - } - - // documentation inherited - protected void delegatesToString (StringBuffer buf) - { - buf.append(portal); - } + public String targetPortalName; // documentation inherited protected void toString (StringBuffer buf) { super.toString(buf); + buf.append(", name=").append(name); buf.append(", targetScene=").append(targetSceneName); - buf.append(", targetLoc=").append(targetLocName); + buf.append(", targetPortal=").append(targetPortalName); } } diff --git a/src/java/com/threerings/whirled/spot/tools/EditableSpotScene.java b/src/java/com/threerings/whirled/spot/tools/EditableSpotScene.java index 8b8b3c8e1..f0e5effe4 100644 --- a/src/java/com/threerings/whirled/spot/tools/EditableSpotScene.java +++ b/src/java/com/threerings/whirled/spot/tools/EditableSpotScene.java @@ -1,5 +1,5 @@ // -// $Id: EditableSpotScene.java,v 1.3 2001/12/04 22:34:04 mdb Exp $ +// $Id: EditableSpotScene.java,v 1.4 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.tools.spot; @@ -30,12 +30,12 @@ public interface EditableSpotScene /** * Adds a location to this scene. */ - public void addLocation (EditableLocation location); + public void addLocation (Location location); /** * Removes the specified location from the scene. */ - public void removeLocation (EditableLocation location); + public void removeLocation (Location location); /** * Adds a portal to this scene (it should be added appropriately to diff --git a/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneImpl.java b/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneImpl.java index 182c887a1..585691e2d 100644 --- a/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneImpl.java +++ b/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneImpl.java @@ -1,5 +1,5 @@ // -// $Id: EditableSpotSceneImpl.java,v 1.3 2001/12/04 22:34:04 mdb Exp $ +// $Id: EditableSpotSceneImpl.java,v 1.4 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.tools.spot; @@ -56,36 +56,29 @@ public class EditableSpotSceneImpl // we're extending from the DisplaySceneImpl class chain _edelegate = new EditableSceneImpl(model); - // create our editable location and portal arrays. here the lack - // of multiple inheritance fucks us even harder. we have to let - // the DisplaySceneImpl maintain arrays of locations and portals - // and we maintain mirror arrays for our editable wrappers which - // delegate to the instances in the display scene's arrays. at - // least we can use array lists here to minimize the pain - int lcount = _locations.length; - int pidx = 0; - for (int i = 0; i < lcount; i++) { - EditableLocation loc; - - if (_locations[i] instanceof Portal) { - loc = new EditablePortal( - _portals[pidx], _emodel.locationNames[i], - _emodel.neighborNames[pidx], _emodel.targetLocNames[pidx]); - pidx++; - - // add portals to the portals array - _eportals.add(loc); - - } else { - loc = new EditableLocation( - _locations[i], _emodel.locationNames[i]); - } - - // everything goes into the locations array - _elocations.add(loc); + // go through and finish populating our editable portals + for (int i = 0; i < _portals.length; i++) { + EditablePortal port = (EditablePortal)_portals[i]; + port.name = _emodel.portalNames[i]; + port.targetSceneName = (String)_emodel.neighborNames.get(i); + port.targetPortalName = _emodel.targetPortalNames[i]; } } + // documentation inherited + protected Portal createPortal () + { + return new EditablePortal(); + } + + /** + * Creates an instance that will create and use a blank scene model. + */ + public EditableSpotSceneImpl () + { + this(EditableSpotSceneModel.blankSpotSceneModel()); + } + // documentation inherited public void setId (int sceneId) { @@ -120,7 +113,7 @@ public class EditableSpotSceneImpl } // documentation inherited - public String[] getNeighborNames () + public ArrayList getNeighborNames () { String errmsg = "Neighbor names can't be fetched directly from the " + "EditableSpotScene because we need to know the associated " + @@ -129,9 +122,18 @@ public class EditableSpotSceneImpl } // documentation inherited - public void setNeighborNames (String[] neighborNames) + public void addNeighbor (String neighborName) { - String errmsg = "Neighbor names can't be set directly in the " + + String errmsg = "Neighbors can't be added directly in the " + + "EditableSpotScene because we need to know the associated " + + "location information to go along with our neighbor connections."; + throw new RuntimeException(errmsg); + } + + // documentation inherited + public boolean removeNeighbor (String neighborName) + { + String errmsg = "Neighbors can't be remove directly in the " + "EditableSpotScene because we need to know the associated " + "location information to go along with our neighbor connections."; throw new RuntimeException(errmsg); @@ -144,27 +146,24 @@ public class EditableSpotSceneImpl } // documentation inherited - public void addLocation (EditableLocation eloc) + public void addLocation (Location loc) { // add the delegate location to the end of the location array int lcount = _locations.length; Location[] nlocs = new Location[lcount+1]; System.arraycopy(_locations, 0, nlocs, 0, lcount); - nlocs[lcount] = eloc.location; + nlocs[lcount] = loc; _locations = nlocs; - - // add it to the editable locations list - _elocations.add(eloc); } // documentation inherited - public void removeLocation (EditableLocation eloc) + public void removeLocation (Location loc) { // obtain the index of this location - int lidx = ListUtil.indexOfEqual(_locations, eloc.location); + int lidx = ListUtil.indexOfEqual(_locations, loc); if (lidx == -1) { Log.warning("Can't remove location that isn't in our array " + - "[loc=" + eloc + "]."); + "[loc=" + loc + "]."); } else { // create a new array minus this location @@ -173,9 +172,6 @@ public class EditableSpotSceneImpl System.arraycopy(_locations, 0, nlocs, 0, lidx); System.arraycopy(_locations, lidx+1, nlocs, lidx, lcount-lidx-1); _locations = nlocs; - - // remove it from the editable locations list - _elocations.remove(lidx); } } @@ -189,11 +185,8 @@ public class EditableSpotSceneImpl int pcount = _portals.length; Portal[] nports = new Portal[pcount+1]; System.arraycopy(_portals, 0, nports, 0, pcount); - nports[pcount] = eport.portal; + nports[pcount] = eport; _portals = nports; - - // and to the editable portals list - _eportals.add(eport); } // documentation inherited @@ -203,7 +196,7 @@ public class EditableSpotSceneImpl removeLocation(eport); // and remove it from the portals array - int pidx = ListUtil.indexOfEqual(_portals, eport.portal); + int pidx = ListUtil.indexOfEqual(_portals, eport); if (pidx == -1) { Log.warning("Can't remove portal that isn't in our array " + "[port=" + eport + "]."); @@ -215,9 +208,6 @@ public class EditableSpotSceneImpl System.arraycopy(_portals, 0, nports, 0, pidx); System.arraycopy(_portals, pidx+1, nports, pidx, pcount-pidx-1); _portals = nports; - - // remove it from the editable portals list - _eportals.remove(pidx); } } @@ -249,7 +239,6 @@ public class EditableSpotSceneImpl _model.locationY = new int[lcount]; _model.locationOrients = new int[lcount]; _model.locationClusters = new int[lcount]; - _emodel.locationNames = new String[lcount]; for (int i = 0; i < lcount; i++) { Location loc = _locations[i]; @@ -258,9 +247,6 @@ public class EditableSpotSceneImpl _model.locationY[i] = loc.y; _model.locationOrients[i] = loc.orientation; _model.locationClusters[i] = loc.clusterIndex; - - EditableLocation eloc = (EditableLocation)_elocations.get(i); - _emodel.locationNames[i] = eloc.name; } // flush the portals @@ -268,19 +254,18 @@ public class EditableSpotSceneImpl _model.portalIds = new int[pcount]; _model.neighborIds = new int[pcount]; _model.targetLocIds = new int[pcount]; - _model.targetLocIds = new int[pcount]; - _emodel.neighborNames = new String[pcount]; - _emodel.targetLocNames = new String[pcount]; + _emodel.neighborNames = new ArrayList(); + _emodel.portalNames = new String[pcount]; + _emodel.targetPortalNames = new String[pcount]; for (int i = 0; i < pcount; i++) { - Portal port = _portals[i]; + EditablePortal port = (EditablePortal)_portals[i]; _model.portalIds[i] = port.locationId; _model.neighborIds[i] = port.targetSceneId; - _model.targetLocIds[i] = port.targetLocationId; - - EditablePortal eport = (EditablePortal)_eportals.get(i); - _emodel.neighborNames[i] = eport.targetSceneName; - _emodel.targetLocNames[i] = eport.targetLocName; + _model.targetLocIds[i] = port.targetLocId; + _emodel.portalNames[i] = port.name; + _emodel.neighborNames.add(port.targetSceneName); + _emodel.targetPortalNames[i] = port.targetPortalName; } } diff --git a/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneModel.java b/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneModel.java index 7c356f640..cb0dacf78 100644 --- a/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneModel.java +++ b/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneModel.java @@ -1,8 +1,10 @@ // -// $Id: EditableSpotSceneModel.java,v 1.1 2001/12/04 22:34:04 mdb Exp $ +// $Id: EditableSpotSceneModel.java,v 1.2 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.tools.spot; +import com.samskivert.util.StringUtil; + import com.threerings.whirled.spot.data.SpotSceneModel; import com.threerings.whirled.tools.EditableSceneModel; @@ -11,10 +13,58 @@ public class EditableSpotSceneModel extends EditableSceneModel /** The spot scene model that we extend with editable info. */ public SpotSceneModel spotSceneModel; - /** The names of the locations in this scene. */ - public String[] locationNames; + /** The names of the portals in this scene. */ + public String[] portalNames; - /** The names of the locations in neighboring scenes to which our + /** The names of the portals in neighboring scenes to which our * portals link. */ - public String[] targetLocNames; + public String[] targetPortalNames; + + /** + * Derived classes override this to tack their toString + * data on to the string buffer. + */ + protected void delegatesToString (StringBuffer buf) + { + buf.append(spotSceneModel); + } + + /** + * Derived classes override this to tack their toString + * data on to the string buffer. + */ + protected void toString (StringBuffer buf) + { + super.toString(buf); + buf.append(", portalNames="). + append(StringUtil.toString(portalNames)); + buf.append(", targetPortalNames="). + append(StringUtil.toString(targetPortalNames)); + } + + /** + * Creates and returns a blank scene model. + */ + public static EditableSpotSceneModel blankSpotSceneModel () + { + EditableSpotSceneModel model = new EditableSpotSceneModel(); + model.spotSceneModel = SpotSceneModel.blankSpotSceneModel(); + model.sceneModel = model.spotSceneModel; + populateBlankSpotSceneModel(model); + return model; + } + + /** + * Populates a blank scene model with blank values. + */ + protected static void populateBlankSpotSceneModel ( + EditableSpotSceneModel model) + { + // populate our superclass fields + populateBlankSceneModel(model); + + // now populate our fields + model.portalNames = new String[0]; + model.targetPortalNames = new String[0]; + } } diff --git a/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParser.java b/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParser.java new file mode 100644 index 000000000..c560e7df7 --- /dev/null +++ b/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParser.java @@ -0,0 +1,59 @@ +// +// $Id: SpotSceneParser.java,v 1.1 2001/12/05 03:38:09 mdb Exp $ + +package com.threerings.whirled.tools.spot.xml; + +import java.io.IOException; +import java.io.FileInputStream; + +import org.xml.sax.SAXException; +import org.apache.commons.digester.Digester; + +import com.threerings.whirled.tools.spot.EditableSpotScene; +import com.threerings.whirled.tools.spot.EditableSpotSceneImpl; + +/** + * A simple class for parsing an editable spot scene instance. + */ +public class SpotSceneParser +{ + /** + * Constructs a scene parser that parses scenes with the specified XML + * path prefix. See the {@link SpotSceneRuleSet#SpotSceneRuleSet} + * documentation for more information. + */ + public SpotSceneParser (String prefix) + { + // create and configure our digester + _digester = new Digester(); + SpotSceneRuleSet set = new SpotSceneRuleSet(); + set.setPrefix(prefix); + _digester.addRuleSet(set); + _digester.addSetNext(prefix, "setScene", + EditableSpotScene.class.getName()); + } + + /** + * Parses the XML file at the specified path into an editable scene + * instance. + */ + public EditableSpotScene parseScene (String path) + throws IOException, SAXException + { + _scene = null; + _digester.push(this); + _digester.parse(new FileInputStream(path)); + return _scene; + } + + /** + * Called by the parser once the scene is parsed. + */ + public void setScene (EditableSpotScene scene) + { + _scene = scene; + } + + protected Digester _digester; + protected EditableSpotScene _scene; +} diff --git a/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java b/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java index 7c78afe16..afe393f3e 100644 --- a/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java +++ b/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java @@ -1,51 +1,51 @@ // -// $Id: SpotSceneRuleSet.java,v 1.1 2001/11/29 19:31:52 mdb Exp $ +// $Id: SpotSceneRuleSet.java,v 1.2 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.tools.spot.xml; import org.apache.commons.digester.Digester; import org.apache.commons.digester.RuleSetBase; -import com.samskivert.xml.SetFieldRule; +import com.samskivert.xml.SetPropertyFieldsRule; -import com.threerings.whirled.spot.data.SpotSceneModel; import com.threerings.whirled.tools.xml.SceneRuleSet; +import com.threerings.whirled.spot.data.Location; +import com.threerings.whirled.tools.spot.EditablePortal; +import com.threerings.whirled.tools.spot.EditableSpotScene; +import com.threerings.whirled.tools.spot.EditableSpotSceneImpl; + /** - * Used to parse a {@link SpotSceneModel} from XML. + * Used to parse an {@link EditableSpotScene} from XML. */ public class SpotSceneRuleSet extends SceneRuleSet { /** - * Adds the necessary rules to the digester to parse our miso scene - * data. + * Extends the scene rule set with the necessary rules to parse our + * spot scene data. */ public void addRuleInstances (Digester digester) { super.addRuleInstances(digester); - // add extra rules for the spot scene model fields - digester.addRule(_prefix + "/locationIds", - new SetFieldRule(digester, "locationIds")); - digester.addRule(_prefix + "/locationX", - new SetFieldRule(digester, "locationX")); - digester.addRule(_prefix + "/locationY", - new SetFieldRule(digester, "locationY")); - digester.addRule(_prefix + "/locationOrients", - new SetFieldRule(digester, "locationOrients")); - digester.addRule(_prefix + "/locationClusters", - new SetFieldRule(digester, "locationClusters")); - digester.addRule(_prefix + "/defaultEntranceId", - new SetFieldRule(digester, "defaultEntranceId")); - digester.addRule(_prefix + "/portalIds", - new SetFieldRule(digester, "portalIds")); - digester.addRule(_prefix + "/targetLocIds", - new SetFieldRule(digester, "targetLocIds")); + // create Location instances when we see + String elclass = Location.class.getName(); + digester.addObjectCreate(_prefix + "/location", elclass); + digester.addRule(_prefix + "/location", + new SetPropertyFieldsRule(digester)); + digester.addSetNext(_prefix + "/location", "addLocation", elclass); + + // create EditablePortal instances when we see + String epclass = EditablePortal.class.getName(); + digester.addObjectCreate(_prefix + "/portal", epclass); + digester.addRule(_prefix + "/portal", + new SetPropertyFieldsRule(digester)); + digester.addSetNext(_prefix + "/portal", "addPortal", epclass); } // documentation inherited - protected Class getSceneModelClass () + protected Class getSceneClass () { - return SpotSceneModel.class; + return EditableSpotSceneImpl.class; } } diff --git a/src/java/com/threerings/whirled/tools/EditableScene.java b/src/java/com/threerings/whirled/tools/EditableScene.java index cfbbc0f41..bac548380 100644 --- a/src/java/com/threerings/whirled/tools/EditableScene.java +++ b/src/java/com/threerings/whirled/tools/EditableScene.java @@ -1,8 +1,10 @@ // -// $Id: EditableScene.java,v 1.2 2001/12/04 22:34:04 mdb Exp $ +// $Id: EditableScene.java,v 1.3 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.tools; +import java.util.ArrayList; + import com.threerings.whirled.client.DisplayScene; import com.threerings.whirled.data.SceneModel; @@ -53,12 +55,21 @@ public interface EditableScene extends DisplayScene /** * Returns the names of the neighbors of this scene. */ - public String[] getNeighborNames (); + public ArrayList getNeighborNames (); /** - * Sets the names of the neighbors of this scene. + * Adds a neighbor to this scene. If the neighbor is already listed + * among the neighbors, it will not be added again. */ - public void setNeighborNames (String[] neighborNames); + public void addNeighbor (String neighborName); + + /** + * Adds a neighbor to this scene. + * + * @return true if the neighbor was removed, false if they were not in + * the neighbor list. + */ + public boolean removeNeighbor (String neighborName); /** * Implementations must provide an editable scene model that diff --git a/src/java/com/threerings/whirled/tools/EditableSceneImpl.java b/src/java/com/threerings/whirled/tools/EditableSceneImpl.java index 4085edef6..660ecdb3c 100644 --- a/src/java/com/threerings/whirled/tools/EditableSceneImpl.java +++ b/src/java/com/threerings/whirled/tools/EditableSceneImpl.java @@ -1,8 +1,10 @@ // -// $Id: EditableSceneImpl.java,v 1.3 2001/12/04 22:34:04 mdb Exp $ +// $Id: EditableSceneImpl.java,v 1.4 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.tools; +import java.util.ArrayList; + import com.threerings.whirled.client.DisplaySceneImpl; import com.threerings.whirled.data.SceneModel; @@ -20,6 +22,15 @@ public class EditableSceneImpl public EditableSceneImpl (EditableSceneModel model) { super(model.sceneModel, null); + _emodel = model; + } + + /** + * Creates an instance that will create and use a blank scene model. + */ + public EditableSceneImpl () + { + this(EditableSceneModel.blankSceneModel()); } // documentation inherited @@ -53,15 +64,23 @@ public class EditableSceneImpl } // documentation inherited - public String[] getNeighborNames () + public ArrayList getNeighborNames () { return _emodel.neighborNames; } // documentation inherited - public void setNeighborNames (String[] neighborNames) + public void addNeighbor (String neighborName) { - _emodel.neighborNames = neighborNames; + if (!_emodel.neighborNames.contains(neighborName)) { + _emodel.neighborNames.add(neighborName); + } + } + + // documentation inherited + public boolean removeNeighbor (String neighborName) + { + return _emodel.neighborNames.remove(neighborName); } // documentation inherited diff --git a/src/java/com/threerings/whirled/tools/EditableSceneModel.java b/src/java/com/threerings/whirled/tools/EditableSceneModel.java index ef6f99e78..9ab5729cb 100644 --- a/src/java/com/threerings/whirled/tools/EditableSceneModel.java +++ b/src/java/com/threerings/whirled/tools/EditableSceneModel.java @@ -1,8 +1,11 @@ // -// $Id: EditableSceneModel.java,v 1.1 2001/12/04 22:34:04 mdb Exp $ +// $Id: EditableSceneModel.java,v 1.2 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.tools; +import java.util.ArrayList; +import com.samskivert.util.StringUtil; + import com.threerings.whirled.data.SceneModel; /** @@ -18,5 +21,56 @@ public class EditableSceneModel public String sceneName; /** The human readable name of this scene's neighbors. */ - public String[] neighborNames; + public ArrayList neighborNames; + + /** + * Generates a string representation of this scene model. + */ + public String toString () + { + StringBuffer buf = new StringBuffer("["); + delegatesToString(buf); + toString(buf); + return buf.append("]").toString(); + } + + /** + * Derived classes override this to tack their toString + * data on to the string buffer. + */ + protected void delegatesToString (StringBuffer buf) + { + buf.append(sceneModel); + } + + /** + * Derived classes override this to tack their toString + * data on to the string buffer. + */ + protected void toString (StringBuffer buf) + { + buf.append(", sceneName=").append(sceneName); + buf.append(", neighborNames="). + append(StringUtil.toString(neighborNames)); + } + + /** + * Creates and returns a blank editable scene model. + */ + public static EditableSceneModel blankSceneModel () + { + EditableSceneModel model = new EditableSceneModel(); + model.sceneModel = SceneModel.blankSceneModel(); + populateBlankSceneModel(model); + return model; + } + + /** + * Populates a blank editable scene model with blank values. + */ + protected static void populateBlankSceneModel (EditableSceneModel model) + { + model.sceneName = ""; + model.neighborNames = new ArrayList(); + } } diff --git a/src/java/com/threerings/whirled/tools/xml/SceneParser.java b/src/java/com/threerings/whirled/tools/xml/SceneParser.java new file mode 100644 index 000000000..35445ba07 --- /dev/null +++ b/src/java/com/threerings/whirled/tools/xml/SceneParser.java @@ -0,0 +1,58 @@ +// +// $Id: SceneParser.java,v 1.1 2001/12/05 03:38:09 mdb Exp $ + +package com.threerings.whirled.tools.xml; + +import java.io.IOException; +import java.io.FileInputStream; + +import org.xml.sax.SAXException; +import org.apache.commons.digester.Digester; + +import com.threerings.whirled.tools.EditableScene; +import com.threerings.whirled.tools.EditableSceneImpl; + +/** + * A simple class for parsing an editable scene instance. + */ +public class SceneParser +{ + /** + * Constructs a scene parser that parses scenes with the specified XML + * path prefix. See the {@link SceneRuleSet#SceneRuleSet} + * documentation for more information. + */ + public SceneParser (String prefix) + { + // create and configure our digester + _digester = new Digester(); + SceneRuleSet set = new SceneRuleSet(); + set.setPrefix(prefix); + _digester.addRuleSet(set); + _digester.addSetNext(prefix, "setScene", EditableScene.class.getName()); + } + + /** + * Parses the XML file at the specified path into an editable scene + * instance. + */ + public EditableScene parseScene (String path) + throws IOException, SAXException + { + _scene = null; + _digester.push(this); + _digester.parse(new FileInputStream(path)); + return _scene; + } + + /** + * Called by the parser once the scene is parsed. + */ + public void setScene (EditableScene scene) + { + _scene = scene; + } + + protected Digester _digester; + protected EditableScene _scene; +} diff --git a/src/java/com/threerings/whirled/tools/xml/SceneRuleSet.java b/src/java/com/threerings/whirled/tools/xml/SceneRuleSet.java index 360450ba2..2cf5164fa 100644 --- a/src/java/com/threerings/whirled/tools/xml/SceneRuleSet.java +++ b/src/java/com/threerings/whirled/tools/xml/SceneRuleSet.java @@ -1,17 +1,16 @@ // -// $Id: SceneRuleSet.java,v 1.1 2001/11/29 19:31:52 mdb Exp $ +// $Id: SceneRuleSet.java,v 1.2 2001/12/05 03:38:09 mdb Exp $ package com.threerings.whirled.tools.xml; import org.apache.commons.digester.Digester; import org.apache.commons.digester.RuleSetBase; -import com.samskivert.xml.SetFieldRule; - -import com.threerings.whirled.data.SceneModel; +import com.threerings.whirled.tools.EditableScene; +import com.threerings.whirled.tools.EditableSceneImpl; /** - * Used to parse a {@link SceneModel} from XML. + * Used to parse an {@link EditableScene} from XML. */ public class SceneRuleSet extends RuleSetBase { @@ -21,9 +20,9 @@ public class SceneRuleSet extends RuleSetBase * scene in the following XML file: * *
-     * <scene>
-     *   <sceneId>50</sceneId>
-     *   <version>50</version>
+     * <scene name="Scene Name" version="3">
+     *   <neighbor>North Scene</neighbor>
+     *   <neighbor>West Scene</neighbor>
      *   <!-- ... -->
      * </scene>
      * 
@@ -39,26 +38,21 @@ public class SceneRuleSet extends RuleSetBase */ public void addRuleInstances (Digester digester) { - // this creates the appropriate instance when we encounter our - // prefix tag - digester.addObjectCreate(_prefix, getSceneModelClass().getName()); + // this creates the appropriate instance when we encounter our tag + digester.addObjectCreate(_prefix, getSceneClass().getName()); // set up rules to parse and set our fields - digester.addRule(_prefix + "/sceneId", - new SetFieldRule(digester, "sceneId")); - digester.addRule(_prefix + "/version", - new SetFieldRule(digester, "version")); - digester.addRule(_prefix + "/neighborIds", - new SetFieldRule(digester, "neighborIds")); + digester.addSetProperties(_prefix); + digester.addCallMethod(_prefix + "/neighbor", "addNeighbor", 0); } /** - * This indicates the class (which should derive from {@link - * SceneModel}) to be instantiated during the parsing process. + * This indicates the class (which should implement {@link + * EditableScene}) to be instantiated during the parsing process. */ - protected Class getSceneModelClass () + protected Class getSceneClass () { - return SceneModel.class; + return EditableSceneImpl.class; } /** The prefix at which me match our scenes. */ diff --git a/tests/rsrc/whirled/spot/tools/xml/scene.xml b/tests/rsrc/whirled/spot/tools/xml/scene.xml new file mode 100644 index 000000000..eb0c4914a --- /dev/null +++ b/tests/rsrc/whirled/spot/tools/xml/scene.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/tests/rsrc/whirled/tools/xml/scene.xml b/tests/rsrc/whirled/tools/xml/scene.xml new file mode 100644 index 000000000..542b407f9 --- /dev/null +++ b/tests/rsrc/whirled/tools/xml/scene.xml @@ -0,0 +1,8 @@ + + + + + Some neighbor + Some other neighbor + Yet another neighbor + diff --git a/tests/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParserTest.java b/tests/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParserTest.java new file mode 100644 index 000000000..c6fefae10 --- /dev/null +++ b/tests/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParserTest.java @@ -0,0 +1,47 @@ +// +// $Id: SpotSceneParserTest.java,v 1.1 2001/12/05 03:38:09 mdb Exp $ + +package com.threerings.whirled.tools.spot.xml; + +import com.samskivert.test.TestUtil; + +import junit.framework.Test; +import junit.framework.TestCase; + +import com.threerings.whirled.tools.spot.EditableSpotScene; + +public class SpotSceneParserTest extends TestCase +{ + public SpotSceneParserTest () + { + super(SpotSceneParserTest.class.getName()); + } + + public void runTest () + { + try { + SpotSceneParser parser = new SpotSceneParser("scene"); + String tspath = TestUtil.getResourcePath(TEST_SCENE_PATH); + EditableSpotScene scene = parser.parseScene(tspath); + System.out.println("Parsed " + scene.getSpotSceneModel() + "."); + + } catch (Exception e) { + e.printStackTrace(); + fail("Test threw exception"); + } + } + + public static Test suite () + { + return new SpotSceneParserTest(); + } + + public static void main (String[] args) + { + SpotSceneParserTest test = new SpotSceneParserTest(); + test.runTest(); + } + + protected static final String TEST_SCENE_PATH = + "whirled/tools/spot/xml/scene.xml"; +} diff --git a/tests/src/java/com/threerings/whirled/tools/xml/SceneParserTest.java b/tests/src/java/com/threerings/whirled/tools/xml/SceneParserTest.java new file mode 100644 index 000000000..a723a2e18 --- /dev/null +++ b/tests/src/java/com/threerings/whirled/tools/xml/SceneParserTest.java @@ -0,0 +1,47 @@ +// +// $Id: SceneParserTest.java,v 1.1 2001/12/05 03:38:10 mdb Exp $ + +package com.threerings.whirled.tools.xml; + +import com.samskivert.test.TestUtil; + +import junit.framework.Test; +import junit.framework.TestCase; + +import com.threerings.whirled.tools.EditableScene; + +public class SceneParserTest extends TestCase +{ + public SceneParserTest () + { + super(SceneParserTest.class.getName()); + } + + public void runTest () + { + try { + SceneParser parser = new SceneParser("scene"); + String tspath = TestUtil.getResourcePath(TEST_SCENE_PATH); + EditableScene scene = parser.parseScene(tspath); + System.out.println("Parsed " + scene.getSceneModel() + "."); + + } catch (Exception e) { + e.printStackTrace(); + fail("Test threw exception"); + } + } + + public static Test suite () + { + return new SceneParserTest(); + } + + public static void main (String[] args) + { + SceneParserTest test = new SceneParserTest(); + test.runTest(); + } + + protected static final String TEST_SCENE_PATH = + "whirled/tools/xml/scene.xml"; +}