/* * Copyright 2014 Google Inc. All rights reserved. * * 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.google.samples.apps.iosched.server.schedule.server.input; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.samples.apps.iosched.server.schedule.Config; import com.google.samples.apps.iosched.server.schedule.input.fetcher.EntityFetcher; import com.google.samples.apps.iosched.server.schedule.input.fetcher.VendorAPIEntityFetcher; import com.google.samples.apps.iosched.server.schedule.model.InputJsonKeys; import java.io.IOException; import java.util.HashMap; /** * Encapsulation of the VendorAPI fetcher. */ public class VendorDynamicInput extends DataSourceInput<InputJsonKeys.VendorAPISource.MainTypes> { private boolean extractUnpublished = Config.SHOW_UNPUBLISHED_DATA; public VendorDynamicInput() { super(new VendorAPIEntityFetcher()); } public VendorDynamicInput(EntityFetcher fetcher) { super(fetcher); } public void setExtractUnpublished(boolean extractUnpublished) { this.extractUnpublished = extractUnpublished; } @Override public Class<InputJsonKeys.VendorAPISource.MainTypes> getType() { return InputJsonKeys.VendorAPISource.MainTypes.class; } @Override public JsonArray fetch(InputJsonKeys.VendorAPISource.MainTypes entityType) throws IOException { return fetchArray(entityType, 1); } public JsonArray fetchArray(InputJsonKeys.VendorAPISource.MainTypes entityType, int page) throws IOException { HashMap<String, String> params = null; if (entityType.equals(InputJsonKeys.VendorAPISource.MainTypes.topics) || entityType.equals(InputJsonKeys.VendorAPISource.MainTypes.speakers)) { params = new HashMap<String, String>(); // Topics and speakers require param "includeinfo=true" to bring extra data params.put("includeinfo", "true"); if (entityType.equals(InputJsonKeys.VendorAPISource.MainTypes.topics)) { if (extractUnpublished) { params.put("minpublishstatus", "0"); } } } if (page == 0) { page = 1; } else if (page > 1) { if (params == null) { params = new HashMap<String, String>(); } params.put("page", Integer.toString(page)); } JsonElement element = getFetcher().fetch(entityType, params); if (element.isJsonArray()) { return element.getAsJsonArray(); } else if (element.isJsonObject()) { // check if there are extra pages requiring further fetching JsonObject obj = element.getAsJsonObject(); checkPagingConsistency(entityType, page, obj); int pageSize = obj.get("pagesize").getAsInt(); int totalEntities = obj.get("total").getAsInt(); JsonArray elements = getEntities(obj); if (page*pageSize < totalEntities) { // fetch the next page elements.addAll(fetchArray(entityType, page+1)); } return elements; } else { throw new JsonParseException("Invalid response from Vendor API. Request should return " + "either a JsonArray or a JsonObject, but returned "+element.getClass().getName() +". Entity fetcher is "+getFetcher()); } } private void checkPagingConsistency(InputJsonKeys.VendorAPISource.MainTypes entityType, int requestedPage, JsonObject obj) { if (!obj.has("page") || !obj.has("pagesize") || !obj.has("total") || (!obj.has("results") && !obj.has("topics"))) { throw new JsonParseException("Invalid response from Vendor API when" + "paging "+entityType+" results. At least one of the required properties " + "(page, pagesize, total, results|topics) could not be found."); } int currentPage = obj.get("page").getAsInt(); if (requestedPage>0 && requestedPage != currentPage) { throw new JsonParseException("Invalid response from Vendor API when" + "paging "+entityType+" results. Requested page "+requestedPage +" but got page "+currentPage); } } private JsonArray getEntities(JsonObject pagedObject) { JsonArray elements; if (pagedObject.has("results")) { elements = pagedObject.get("results").getAsJsonArray(); } else if (pagedObject.has("topics")) { elements = pagedObject.get("topics").getAsJsonArray(); } else { throw new JsonParseException("Invalid JSON format for a paged result. Expected either a \"results\" or a topics array property."); } return elements; } }