     }
   }
 
+}
+
+private class QueryBuilder {
+  
+  private let query: Query
+  
+  init(query: Query) {
+    self.query = query
+  }
+  
+  private func build(topLevel topLevel: Bool) throws -> String {
+    var queryString = topLevel ? "{\n" : ""
+    
+    for (i, collection) in query.collections.enumerate() {
+      queryString += "\(collection)\(try buildArguments(forCollection: collection)) {\n"
+      queryString += try buildFields(forCollection: collection)
+      if !query.subQueries.isEmpty {
+        queryString += try ",\n" + buildSubQueries()
+      } else {
+        queryString += "\n}"
+      }
+      queryString += joinCollections(i)
+    }
+    queryString += "\n}"
+    
+    return queryString
+  }
+  
   private func joinCollections(current: Int) -> String {
-    return current == collections.count - 1 ? "" : ",\n"
+    return current == query.collections.count - 1 ? "" : ",\n"
   }
-
-  private func buildArguments(forCollection collection: String) -> String {
-    guard let arguments = arguments[collection] else {
+  
+  private func buildArguments(forCollection collection: String) throws -> String {
+    guard let arguments = query.arguments[collection] else {
       return ""
     }
+    guard !arguments.isEmpty else { throw QueryError.MissingArguments }
     var args = "("
     args += arguments.flatMap{ $0.build() }.joinWithSeparator(", ")
     args += ")"


  private func build(topLevel topLevel: Bool) throws -> String {
    try validateQuery()
    
    var query = topLevel ? "{\n" : ""
    
    for (i, collection) in collections.enumerate() {
      query += "\(collection)\(buildArguments(forCollection: collection)) {\n"
      query += try buildFields(forCollection: collection)
      if !subQueries.isEmpty {
        query += try ",\n" + buildSubQueries()
      } else {
        query += "\n}"
      }
      query += joinCollections(i)
    }
    query += "\n}"

    return query
  }
  
  private func validateQuery() throws {
    if collections.isEmpty {
      throw QueryError.MissingCollection

public enum QueryError: ErrorType {
  case MissingCollection
  case MissingFields
  case MissingArguments
  case InvalidState(String)
}

