Java tutorial
/* * Copyright 2012-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.json; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.stream.JsonReader; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.List; import java.util.Map; /** * This is a special JSON parser that is customized to consume the JSON output of buck.py. * Object values may be one of: null, a string, or an array of strings. This means that no * sort of nested arrays or objects are allowed in the output as Parser is implemented * today. This simplification makes it easier to leverage Jackson's streaming JSON API. */ public class BuildFileToJsonParser implements AutoCloseable { /** * The parser below uses these objects for stateful purposes with the ultimate goal * of populating the parsed rules into `currentObjects`. * * The parser is expecting output in the form: * [{"key": "value"}, {"key": "value"}, ...] * * This is a necessary short-term step to keep logic in the main Parser consistent (expecting to * be able to correlate a set of rules with the specific BUCK file that generated them). This * requirement creates an unnecessary performance weakness in this design where we cannot * parallelize buck.py's parsing of BUCK files with buck's processing of the result into a DAG. */ private final Gson gson; private final JsonReader reader; /** * @param jsonReader That contains the JSON data. */ public BuildFileToJsonParser(Reader jsonReader) { this.gson = new Gson(); this.reader = new JsonReader(jsonReader); // This is used to read one line at a time. reader.setLenient(true); } @VisibleForTesting public BuildFileToJsonParser(String json) { this(new StringReader(json)); } /** * Access the next set of rules from the build file processor. Note that for non-server * invocations, this will collect all of the rules into one enormous list. * * @return The parsed JSON, represented as Java collections. Ideally, we would use Gson's object * model directly to avoid the overhead of converting between object models. That would * require updating all code that depends on this method, which may be a lot of work. Also, * bear in mind that using the Java collections decouples clients of this method from the JSON * parser that we use. */ @SuppressWarnings("unchecked") List<Map<String, Object>> nextRules() throws IOException { try { List<Map<String, Object>> items = Lists.newArrayList(); reader.beginArray(); while (reader.hasNext()) { JsonObject json = gson.fromJson(reader, JsonObject.class); items.add((Map<String, Object>) RawParser.toRawTypes(json)); } reader.endArray(); return items; } catch (IllegalStateException e) { throw new IOException(e); // Rethrow Gson exceptions as IO (non-runtime) exceptions. } } @Override public void close() throws IOException { reader.close(); } }