Skip to content

Instantly share code, notes, and snippets.

@peralmq
Last active January 10, 2016 17:49
Show Gist options
  • Save peralmq/e10cc04a8e33bac5ffd8 to your computer and use it in GitHub Desktop.
Save peralmq/e10cc04a8e33bac5ffd8 to your computer and use it in GitHub Desktop.
BoardGameGeek API client in Kotlin

BoardGameGeek(BGG) as the name implies is a site with focus on board games. This is a client for the BGG XML API that holds a big repository of board game data. The client is written in Kotlin which enables it to be incorporated easily in Java (JVM) environments. This code will most likely be used in an upcoming Android pet project of mine.

Say you want to search for the game "Power Grid" from within your Android app, then the client can be used like this:

val games = BoardGameGeek().searchGames("Power Grid")
println(games)
// BoardGames(games=[BoardGame(id=2651, name=Power Grid, yearpublished=2004), ...)])
import android.util.Xml
import org.xmlpull.v1.XmlPullParser
import java.io.InputStream
import java.net.URL
import java.util.*
data class BoardGame(val id: Int, val name: String?, val yearpublished: Int?)
data class BoardGames(val games: List<BoardGame>)
public class BoardGameGeek {
companion object {
private val BASE_URL = "http://www.boardgamegeek.com/xmlapi/"
private val ns: String? = null
}
fun searchGames(query: String): BoardGames {
val response = URL(BASE_URL + "search?search=" + query).readText() //TODO urlEncode
val parser = createParser(response.byteInputStream())
return readGames(parser)
}
private fun createParser(`in`: InputStream): XmlPullParser {
try {
val parser = Xml.newPullParser()
parser.setInput(`in`, null)
parser.next()
return parser
} finally {
`in`.close()
}
}
private fun readGames(parser: XmlPullParser): BoardGames {
val games = ArrayList<BoardGame>()
parser.require(XmlPullParser.START_TAG, ns, "boardgames")
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.eventType != XmlPullParser.START_TAG) {
continue
}
if (parser.name == "boardgame") {
games.add(readGame(parser))
} else {
skip(parser)
}
}
return BoardGames(games)
}
private fun readGame(parser: XmlPullParser): BoardGame {
parser.require(XmlPullParser.START_TAG, ns, "boardgame")
val id: Int = readId(parser)
var name: String? = null
var yearpublished: Int? = null
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.eventType != XmlPullParser.START_TAG) {
continue
}
val tag = parser.name
if (tag == "name") {
name = readName(parser)
} else if (tag == "yearpublished") {
yearpublished = readYearpublished(parser)
} else {
skip(parser)
}
}
return BoardGame(id, name, yearpublished)
}
private fun readName(parser: XmlPullParser): String {
parser.require(XmlPullParser.START_TAG, ns, "name")
val name = readText(parser)
parser.require(XmlPullParser.END_TAG, ns, "name")
return name
}
private fun readYearpublished(parser: XmlPullParser): Int {
parser.require(XmlPullParser.START_TAG, ns, "yearpublished")
val yearpublished = readText(parser).toInt()
parser.require(XmlPullParser.END_TAG, ns, "yearpublished")
return yearpublished
}
private fun readId(parser: XmlPullParser): Int {
var id = parser.getAttributeValue(null, "objectid").toInt()
return id
}
private fun readText(parser: XmlPullParser): String {
var result = ""
if (parser.next() == XmlPullParser.TEXT) {
result = parser.text
parser.nextTag()
}
return result
}
private fun skip(parser: XmlPullParser) {
if (parser.eventType != XmlPullParser.START_TAG) {
throw IllegalStateException()
}
var depth = 1
while (depth != 0) {
when (parser.next()) {
XmlPullParser.END_TAG -> depth--
XmlPullParser.START_TAG -> depth++
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment