/* * Copyright (C) 2010-2012 Stichting Akvo (Akvo Foundation) * * This file is part of Akvo FLOW. * * Akvo FLOW is free software: you can redistribute it and modify it under the terms of * the GNU Affero General Public License (AGPL) as published by the Free Software Foundation, * either version 3 of the License or any later version. * * Akvo FLOW is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License included below for more details. * * The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>. */ package com.gallatinsystems.framework.analytics.summarization; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import com.gallatinsystems.framework.rest.AbstractRestApiServlet; import com.gallatinsystems.framework.rest.RestRequest; import com.gallatinsystems.framework.rest.RestResponse; import com.google.appengine.api.taskqueue.Queue; import com.google.appengine.api.taskqueue.QueueFactory; import com.google.appengine.api.taskqueue.TaskOptions; /** * Performs data summarization based on a statically defined list of summarizers (configured via the * init params) * * @author Christopher Fagiani */ public abstract class DataSummarizationHandler extends AbstractRestApiServlet { private static final long serialVersionUID = 1689300636699166004L; protected Map<String, List<String>> summarizers; protected String queueName; protected String summarizerPath; public DataSummarizationHandler() { super(); initializeSummarization(); } /** * initializes the list of summarizers and the queue names/paths */ protected abstract void initializeSummarization(); @Override protected RestRequest convertRequest() throws Exception { HttpServletRequest req = getRequest(); DataSummarizationRequest restRequest = new DataSummarizationRequest(); restRequest.populateFromHttpRequest(req); return restRequest; } /** * looks up the appropriate summarizer in the summarizer map (using the Type passed in on the * request) then finds the name of the summarization and, if found, runs it. After running, if * there are more summarizations left in the list, it updates the action on the request with the * next value and puts the request back on the queue. */ @SuppressWarnings("rawtypes") @Override protected RestResponse handleRequest(RestRequest request) throws Exception { RestResponse response = new RestResponse(); DataSummarizationRequest summarizationRequest = (DataSummarizationRequest) request; int idx = 0; List<String> applicableSummarizers = summarizers .get(summarizationRequest.getType()); if (applicableSummarizers != null) { if (request.getAction() != null) { while (idx < applicableSummarizers.size()) { if (applicableSummarizers.get(idx).trim().equals( summarizationRequest.getAction())) { break; } idx++; } } if (idx < applicableSummarizers.size()) { boolean isCompleted = false; DataSummarizer summarizer = null; try { Class cls = Class.forName(applicableSummarizers.get(idx)); summarizer = (DataSummarizer) cls .newInstance(); isCompleted = summarizer.performSummarization( summarizationRequest.getObjectKey(), summarizationRequest.getType(), summarizationRequest.getValue(), summarizationRequest.getOffset(), summarizationRequest.getCursor()); } catch (Exception e) { log( "Could not invoke summarizer. Setting complete to true to continue with processing", e); isCompleted = true; } if (!isCompleted && summarizer != null) { // if we're not done, increment offset and call the same // summarizer summarizationRequest.setAction(applicableSummarizers .get(idx)); summarizationRequest.setOffset(summarizationRequest .getOffset() + DataSummarizer.BATCH_SIZE); summarizationRequest.setCursor(summarizer.getCursor()); invokeSummarizer(summarizationRequest); } else { if (idx < applicableSummarizers.size() - 1) { summarizationRequest.setAction(applicableSummarizers .get(idx + 1)); // put the item back on the queue with the action // updated to the next summarization in the chain invokeSummarizer(summarizationRequest); } } } } else { log("No summarizers configured for type " + summarizationRequest.getType()); } return response; } /** * puts the summarization request into the queue * * @param request */ private void invokeSummarizer(DataSummarizationRequest request) { Queue queue = QueueFactory.getQueue(queueName); queue .add(TaskOptions.Builder.withUrl(summarizerPath).param( DataSummarizationRequest.ACTION_PARAM, request.getAction()).param( DataSummarizationRequest.OBJECT_KEY, request.getObjectKey()) .param(DataSummarizationRequest.OBJECT_TYPE, request.getType()).param( DataSummarizationRequest.OFFSET_KEY, request.getOffset().toString()).param( DataSummarizationRequest.CURSOR_PARAM, request.getCursor() != null ? request .getCursor() : "")); } @Override protected void writeOkResponse(RestResponse resp) throws Exception { resp.setCode("200"); } }