 
   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 try QueryBuilder(query: self).build(topLevel: topLevel)
+  }
 
-    return query
-  }
-  
   private func validateQuery() throws {
     if collections.isEmpty {
       throw QueryError.MissingCollection

    }
  }

  private func joinCollections(current: Int) -> String {
    return current == collections.count - 1 ? "" : ",\n"
  }

  private func buildArguments(forCollection collection: String) -> String {
    guard let arguments = arguments[collection] else {
      return ""
    }
    var args = "("
    args += arguments.flatMap{ $0.build() }.joinWithSeparator(", ")
    args += ")"

  }
  
  private func buildFields(forCollection collection: String) throws -> String {
    guard let fields = query.fields[collection] else { throw QueryError.MissingFields }
    guard !fields.isEmpty else { throw QueryError.MissingFields }
    return fields.joinWithSeparator(",\n")
  }
  
  private func buildSubQueries() throws -> String {
    return try query.subQueries.map{ try $0.build(topLevel: false) }.joinWithSeparator(",\n")
  }

}



