We are doing a text-based adventure where you read in the layout from a JSON file. I am reading in a JSON file to create a Layout class which contains room objects. Each room has a map of directions which maps the direction name (ie south, east, west, etc) to the direction object. Inside the layout class, there is another map that maps the room names to the room object. When I run my code, the debugger tells me that my roomMap as well as my directionMap are both null. So when I try to call a JUnit test to make sure that the proper value is returned when I access the maps, I get a NullPointerException.
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
public class Room {
// instance variables
protected String name;
protected String description;
protected Item[] items;
protected Direction[] directions;
protected ArrayList<Direction> testList = new ArrayList<>();
protected HashMap<String, Direction> directionMap = new HashMap<>();
public Room(String name, String description, Direction[] directions, Item[] items) {
this.name = name;
this.description = description;
this.items = items;
this.directions = directions;
for (Direction d : directions) {
directionMap.put(d.directionName, d);
}
}
}
This is my direction class:
package com.example;
import com.sun.org.apache.xpath.internal.operations.Bool;
public class Direction {
// instance variables
protected String room;
protected String directionName;
protected boolean enabled;
protected String[] validKeyNames;
public Direction(String room, String directionName, String enabled, String[] validKeyNames) {
this.room = room;
this.directionName = directionName;
this.enabled = Boolean.parseBoolean(enabled);
this.validKeyNames = validKeyNames;
}
public static boolean compareDirections (Direction d1, Direction d2){
boolean roomMatch = d1.room.equals(d2.room);
boolean nameMatch = d1.directionName.equals(d2.directionName);
boolean enabledMatch = d1.enabled == d2.enabled;
boolean validKeyNamesMatch = true;
if(d1.validKeyNames.length == d2.validKeyNames.length){
for(int i = 0; i < d1.validKeyNames.length; i++){
if(!d1.validKeyNames[i].equals(d2.validKeyNames[i])){
validKeyNamesMatch = false;
}
}
}
return roomMatch && nameMatch && enabledMatch && validKeyNamesMatch;
}
}
This is my Player class:
public class Player {
protected Item[] items;
protected Room currentRoom;
public Player(Item[] items, Room startingRoom){
this.items = items;
this.currentRoom = startingRoom;
}
}
This is my Items class:
public class Item {
protected String name;
public Item(String name){
this.name = name;
}
public static boolean compareItems (Item i1, Item i2){
return i1.name.equals(i2.name);
}
}
And this is my layout class where roomMap is
public class Layout {
// instance variables
protected String startingRoom;
protected String endingRoom;
protected Room[] rooms;
protected Player player;
protected HashMap<String, Room> roomMap = new HashMap<>();
public Layout(String startingRoom, String endingRoom, Room[] rooms, Player player) {
this.startingRoom = startingRoom;
this.endingRoom = endingRoom;
this.rooms = rooms;
this.player = player;
for (Room room : rooms) {
roomMap.put(room.name, room);
}
}
This is the JSON reader class:
public class JsonReader {
public static String getJsonFromUrl (String link) throws IOException {
try{
URL url = new URL(link);
} catch(MalformedURLException e){
System.out.println("That is not a valid link");
System.exit(0);
}
URL url = new URL(link);
// Connect to the URL using java's native library
URLConnection request = url.openConnection();
request.connect();
// Convert to a JSON object to print data
JsonParser jp = new JsonParser(); //from gson
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
JsonObject rootobj = root.getAsJsonObject(); //May be an array, may be an object.
return rootobj.toString();
}
}
I have tested the Gson parser and know for a fact that all the values from the JSON file are being properly serialized, which is why I'm confused that the key-value pair are not being put inside the hashmap.
Here are my JUnit Tests
import com.google.gson.Gson;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import static org.junit.Assert.*;
public class AdventureTest {
Adventure adventure;
@Before
public void setup() {
adventure = new Adventure("https://drive.google.com/uc?export=download&id=1qmmrC3jZ3zrmdvrL8ukM5r4pB4BYhfyd");
}
@Test
public void getJsonFromUrlTest() throws IOException {
assertEquals(
"{\"startingRoom\":\"SDRPCommons\",\"endingRoom\":\"HopkinsRoom345\",\"rooms\":[{\"name\":\"SDRPCommons\",\"description\":\"You are in the Ikenberry Dining Hall. There is good food, good people, and good study areas\",\"directions\":[{\"directionName\":\"North\",\"room\":\"DiningHall\",\"enabled\":\"false\",\"validKeyNames\":[\"I-card\"]},{\"directionName\":\"Northwest\",\"room\":\"UpstairsArea\",\"enabled\":\"true\",\"validKeyNames\":[]},{\"directionName\":\"West\",\"room\":\"OutsideAreaOfSixPack\",\"enabled\":\"false\",\"validKeyNames\":[\"backpack\",\"depression\"]}],\"items\":[{\"name\":\"I-card\"},{\"name\":\"Chair\"},{\"name\":\"Fork\"}]},{\"name\":\"DiningHall\",\"description\":\"The best eats on campus, other than PAR/FAR, Chomps, and basically anything on Green Street.\",\"directions\":[{\"directionName\":\"South\",\"room\":\"SDRPCommons\",\"enabled\":\"true\",\"validKeyNames\":[\"depression\"]}],\"items\":[{\"name\":\"sweatshirt\"},{\"name\":\"key\"}]},{\"name\":\"UpstairsArea\",\"description\":\"You are upstairs. Near you is Caffeinator but it's closed. So there is nothing to do but to go back to your room and grind...\",\"directions\":[{\"directionName\":\"Southeast\",\"room\":\"SDRPCommons\",\"enabled\":\"true\",\"validKeyNames\":[]}],\"items\":[{\"name\":\"depression\"},{\"name\":\"backpack\"}]},{\"name\":\"OutsideAreaOfSixPack\",\"description\":\"It's a beautiful day and everyone is out and about. Kinda makes you want to sit in your room in the dark, right?\",\"directions\":[{\"directionName\":\"North\",\"room\":\"HopkinsRoom345\",\"enabled\":\"false\",\"validKeyNames\":[\"depression\",\"backpack\"]}],\"items\":[{\"name\":\"depression\"},{\"name\":\"backpack\"}]},{\"name\":\"HopkinsRoom345\",\"description\":\"This is your room. Go inside and grind your cs 126 hw, idiot.\",\"directions\":[{\"directionName\":\"South\",\"room\":\"OutsideAreaOfSixPack\",\"enabled\":\"false\",\"validKeyNames\":[\"key\",\"depression\"]}],\"items\":[{\"name\":\"bed\"}]}]}",
JsonReader.getJsonFromUrl("https://drive.google.com/uc?export=download&id=1qmmrC3jZ3zrmdvrL8ukM5r4pB4BYhfyd")
);
}
@Test
public void loadJsonIntoLayout() throws IOException {
String json = JsonReader.getJsonFromUrl("https://drive.google.com/uc?export=download&id=1qmmrC3jZ3zrmdvrL8ukM5r4pB4BYhfyd");
Gson gson = new Gson();
Layout layout = gson.fromJson(json, Layout.class);
if (layout != null) {
assertEquals("SDRPCommons", layout.startingRoom);
// System.out.println(layout.roomMap.get(layout.startingRoom));
Room r = adventure.roomMap.get("DiningHall");
Direction d = adventure.directionMap.get("south");
String s = d.directionName;
assertEquals("south", layout.roomMap.get("DiningHall").directionMap.get("south"));
}
}
}
This is the adventure class:
import com.google.gson.Gson;
import java.io.*;
import java.lang.reflect.Array;
import java.net.*;
import java.util.*;
import static sun.plugin.javascript.navig.JSType.Element;
public class Adventure {
protected Layout layout;
protected HashMap<String, Room> roomMap = new HashMap<>();
protected HashMap<String, Direction> directionMap = new HashMap<>();
// private Player player;
private static String jsonUrl;
// link for easy access: https://drive.google.com/uc?export=download&id=1qmmrC3jZ3zrmdvrL8ukM5r4pB4BYhfyd
protected Room currentRoom;
protected final List<String> ACTION_VERBS = Arrays.asList("go");
protected final List<String> EXIT_VERBS = Arrays.asList("exit", "quit");
protected final List<String> ITEM_VERBS = Arrays.asList("pickup", "use");
public Adventure(String url) {
this.jsonUrl = url;
this.layout = getLayoutFromJson(jsonUrl);
String startingRoom = layout.getStartingRoom();
for (Room r : layout.rooms) {
for (Direction d : r.directions) {
r.directionMap.put(d.directionName, d);
}
layout.roomMap.put(r.name, r);
}
this.currentRoom = roomMap.get(startingRoom);
}
public Layout getLayoutFromJson(String url) {
try {
String json = JsonReader.getJsonFromUrl(url);
Gson gson = new Gson();
Layout layout = gson.fromJson(json, Layout.class);
return layout;
} catch (Exception e) {
return null;
}
}
}