org.opendatakit.aggregate.server.SubmissionServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.opendatakit.aggregate.server.SubmissionServiceImpl.java

Source

/*
 * Copyright (C) 2011 University of Washington
 *
 * 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 org.opendatakit.aggregate.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.net.URLCodec;
import org.opendatakit.aggregate.ContextFactory;
import org.opendatakit.aggregate.client.exception.FormNotAvailableException;
import org.opendatakit.aggregate.client.exception.RequestFailureException;
import org.opendatakit.aggregate.client.filter.FilterGroup;
import org.opendatakit.aggregate.client.submission.SubmissionUI;
import org.opendatakit.aggregate.client.submission.SubmissionUISummary;
import org.opendatakit.aggregate.constants.ErrorConsts;
import org.opendatakit.aggregate.constants.common.FormElementNamespace;
import org.opendatakit.aggregate.datamodel.FormElementModel;
import org.opendatakit.aggregate.exception.ODKFormNotFoundException;
import org.opendatakit.aggregate.form.FormFactory;
import org.opendatakit.aggregate.form.IForm;
import org.opendatakit.aggregate.form.PersistentResults;
import org.opendatakit.aggregate.format.Row;
import org.opendatakit.aggregate.format.element.ElementFormatter;
import org.opendatakit.aggregate.format.element.UiElementFormatter;
import org.opendatakit.aggregate.query.submission.QueryByUIFilterGroup;
import org.opendatakit.aggregate.query.submission.QueryByUIFilterGroup.CompletionFlag;
import org.opendatakit.aggregate.submission.Submission;
import org.opendatakit.aggregate.submission.SubmissionElement;
import org.opendatakit.aggregate.submission.SubmissionKey;
import org.opendatakit.aggregate.submission.SubmissionKeyPart;
import org.opendatakit.aggregate.submission.SubmissionSet;
import org.opendatakit.aggregate.submission.type.BlobSubmissionType;
import org.opendatakit.aggregate.submission.type.RepeatSubmissionType;
import org.opendatakit.common.persistence.client.exception.DatastoreFailureException;
import org.opendatakit.common.persistence.exception.ODKDatastoreException;
import org.opendatakit.common.persistence.exception.ODKOverQuotaException;
import org.opendatakit.common.web.CallingContext;

public class SubmissionServiceImpl extends RemoteServiceServlet
        implements org.opendatakit.aggregate.client.submission.SubmissionService {

    /**
     * Serialization Identifier
     */
    private static final long serialVersionUID = -7997978505247614945L;

    @Override
    public SubmissionUISummary getSubmissions(FilterGroup filterGroup)
            throws FormNotAvailableException, RequestFailureException, DatastoreFailureException {
        HttpServletRequest req = this.getThreadLocalRequest();
        CallingContext cc = ContextFactory.getCallingContext(this, req);

        try {
            String formId = filterGroup.getFormId();
            IForm form = FormFactory.retrieveFormByFormId(formId, cc);
            if (!form.hasValidFormDefinition()) {
                throw new RequestFailureException(ErrorConsts.FORM_DEFINITION_INVALID); // ill-formed
                // definition
            }
            QueryByUIFilterGroup query = new QueryByUIFilterGroup(form, filterGroup,
                    CompletionFlag.ONLY_COMPLETE_SUBMISSIONS, cc);

            SubmissionUISummary summary = new SubmissionUISummary(form.getViewableName());
            GenerateHeaderInfo headerGenerator = new GenerateHeaderInfo(filterGroup, summary, form);
            headerGenerator.processForHeaderInfo(form.getTopLevelGroupElement());
            List<FormElementModel> filteredElements = headerGenerator.getIncludedElements();
            ElementFormatter elemFormatter = new UiElementFormatter(cc.getServerURL(),
                    headerGenerator.getGeopointIncludes());
            List<FormElementNamespace> includedTypes = headerGenerator.includedFormElementNamespaces();
            query.populateSubmissions(summary, filteredElements, elemFormatter, includedTypes, cc);

            return summary;

        } catch (ODKFormNotFoundException e) {
            e.printStackTrace();
            throw new FormNotAvailableException(e);
        } catch (ODKOverQuotaException e) {
            e.printStackTrace();
            throw new RequestFailureException(ErrorConsts.QUOTA_EXCEEDED);
        } catch (ODKDatastoreException e) {
            e.printStackTrace();
            throw new DatastoreFailureException(e);
        }

    }

    @Override
    public SubmissionUISummary getRepeatSubmissions(String keyString)
            throws FormNotAvailableException, RequestFailureException, DatastoreFailureException {
        HttpServletRequest req = this.getThreadLocalRequest();
        CallingContext cc = ContextFactory.getCallingContext(this, req);

        if (keyString == null) {
            return null;
        }

        try {
            SubmissionKey key = new SubmissionKey(keyString);
            List<SubmissionKeyPart> parts = key.splitSubmissionKey();
            IForm form = FormFactory.retrieveFormByFormId(parts.get(0).getElementName(), cc);
            if (!form.hasValidFormDefinition()) {
                throw new RequestFailureException(ErrorConsts.FORM_DEFINITION_INVALID); // ill-formed
                // definition
            }
            Submission sub = Submission.fetchSubmission(parts, cc);

            if (sub != null) {
                SubmissionElement tmp = sub.resolveSubmissionKey(parts);
                RepeatSubmissionType repeat = (RepeatSubmissionType) tmp;

                SubmissionUISummary summary = new SubmissionUISummary(form.getViewableName());
                GenerateHeaderInfo headerGenerator = new GenerateHeaderInfo(null, summary, form);
                headerGenerator.processForHeaderInfo(repeat.getElement());
                List<FormElementModel> filteredElements = headerGenerator.getIncludedElements();
                ElementFormatter elemFormatter = new UiElementFormatter(cc.getServerURL(),
                        headerGenerator.getGeopointIncludes());

                // format row elements
                for (SubmissionSet subSet : repeat.getSubmissionSets()) {
                    Row row = subSet.getFormattedValuesAsRow(filteredElements, elemFormatter, false, cc);
                    try {
                        summary.addSubmission(new SubmissionUI(row.getFormattedValues(), null));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return summary;

            } else {
                return null;
            }

        } catch (ODKFormNotFoundException e) {
            e.printStackTrace();
            throw new FormNotAvailableException(e);
        } catch (ODKOverQuotaException e) {
            e.printStackTrace();
            throw new RequestFailureException(ErrorConsts.QUOTA_EXCEEDED);
        } catch (ODKDatastoreException e) {
            e.printStackTrace();
            throw new DatastoreFailureException(e);
        }
    }

    @Override
    public String getSubmissionAuditCSV(String keyString) throws RequestFailureException {
        HttpServletRequest req = this.getThreadLocalRequest();
        CallingContext cc = ContextFactory.getCallingContext(this, req);

        URLCodec urlCodec = new URLCodec();
        String decode = null;
        try {
            decode = urlCodec.decode(keyString);
        } catch (DecoderException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        SubmissionKey key = new SubmissionKey(decode);

        List<SubmissionKeyPart> parts = key.splitSubmissionKey();
        if (parts.get(0).getElementName().equals(PersistentResults.FORM_ID_PERSISTENT_RESULT))
            return new String(getBytes(cc, key));

        Submission sub = getSubmission(cc, parts);
        BlobSubmissionType b = getBlobSubmissionType(parts, sub);
        return new String(getBytes(cc, parts, b));
    }

    private byte[] getBytes(CallingContext cc, SubmissionKey key) throws RequestFailureException {
        byte[] resultFileContents;
        try {
            PersistentResults p = new PersistentResults(key, cc);
            PersistentResults.ResultFileInfo info = p.getResultFileInfo(cc);
            if (info == null) {
                throw new RequestFailureException("Unable to retrieve attachment");
            }
            resultFileContents = p.getResultFileContents(cc);

        } catch (ODKOverQuotaException e) {
            e.printStackTrace();
            throw new RequestFailureException(e);
        } catch (ODKDatastoreException e) {
            e.printStackTrace();
            throw new RequestFailureException("Unable to retrieve attachment");
        }
        return resultFileContents;
    }

    private byte[] getBytes(CallingContext cc, List<SubmissionKeyPart> parts, BlobSubmissionType b)
            throws RequestFailureException {
        byte[] blob;
        try {
            int ordinal = b.getAttachmentCount(cc);
            if (ordinal != 1) {
                SubmissionKeyPart p = parts.get(parts.size() - 1);
                Long ord = p.getOrdinalNumber();
                if (ord == null) {
                    throw new RequestFailureException("attachment request must be fully qualified");
                }
                ordinal = ord.intValue();
            }
            blob = b.getBlob(ordinal, cc);

        } catch (ODKOverQuotaException e) {
            e.printStackTrace();
            throw new RequestFailureException(e);
        } catch (ODKDatastoreException e) {
            e.printStackTrace();
            throw new RequestFailureException("Unable to retrieve attachment");
        }
        return blob;
    }

    private BlobSubmissionType getBlobSubmissionType(List<SubmissionKeyPart> parts, Submission sub)
            throws RequestFailureException {
        BlobSubmissionType b;

        try {
            SubmissionElement v;
            v = sub.resolveSubmissionKey(parts);
            if (v instanceof BlobSubmissionType) {
                b = (BlobSubmissionType) v;
            } else {
                throw new RequestFailureException("Requested element is not a binary object");
            }
        } catch (Exception e) {
            e.printStackTrace();
            String path = getKeyPath(parts);
            throw new RequestFailureException("Unable to retrieve part identified by path: " + path);
        }
        return b;
    }

    private Submission getSubmission(CallingContext cc, List<SubmissionKeyPart> parts)
            throws RequestFailureException {
        Submission sub;
        try {
            sub = Submission.fetchSubmission(parts, cc);
            assert sub != null;
        } catch (ODKFormNotFoundException e1) {
            throw new RequestFailureException(e1);
        } catch (ODKOverQuotaException e) {
            e.printStackTrace();
            throw new RequestFailureException(e);
        } catch (ODKDatastoreException e) {
            e.printStackTrace();
            throw new RequestFailureException("Unable to retrieve attachment");
        }
        return sub;
    }

    private final String getKeyPath(List<SubmissionKeyPart> parts) {
        StringBuilder b = new StringBuilder();
        for (SubmissionKeyPart p : parts) {
            b.append("/");
            b.append(p.toString());
        }
        return b.toString();
    }
}