Package org.locationtech.geogig.rest.osm

Source Code of org.locationtech.geogig.rest.osm.OsmDownloadWebOp

/* Copyright (c) 2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Gabriel Roldan (Boundless) - initial implementation
*/
package org.locationtech.geogig.rest.osm;

import java.io.File;
import java.net.URL;
import java.util.List;

import javax.annotation.Nullable;

import org.locationtech.geogig.api.AbstractGeoGigOp;
import org.locationtech.geogig.api.Context;
import org.locationtech.geogig.osm.internal.OSMDownloadOp;
import org.locationtech.geogig.osm.internal.OSMReport;
import org.locationtech.geogig.osm.internal.OSMUpdateOp;
import org.locationtech.geogig.osm.internal.OSMUtils;
import org.locationtech.geogig.rest.AsyncContext;
import org.locationtech.geogig.rest.AsyncContext.AsyncCommand;
import org.locationtech.geogig.rest.TransactionalResource;
import org.locationtech.geogig.rest.Variants;
import org.locationtech.geogig.web.api.CommandSpecException;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.Representation;
import org.restlet.resource.Variant;

import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;

/**
* Imports data from OSM using the Overpass API.
* <ul>
* <li>filter: Optional, or mandatory if {@code bbox} is not give. The filter file to use. Must
* exist in the server filesystem and contain an <a
* href="http://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL">Overpass QL filter</a>.
* <li>bbox: Mandatory if {@code filter} is not given. The bounding box to use as filter, in WGS84
* coordinates. Format: {@code <S>,<W>,<N>,<E>}.
* <li>message: Message for the commit to create.
* <li>update: Boolean. Default: false. Update the OSM data currently in the geogig repository
* <li>rebase: Boolean. Default: false. Use rebase instead of merge when updating. Can only be true
* if upate = true.
* <li>mapping: The file that contains the data mapping to use".
* </ul>
*
*/
public class OsmDownloadWebOp extends TransactionalResource {

    @Override
    public void init(org.restlet.Context context, Request request, Response response) {
        super.init(context, request, response);
        getVariants().add(Variants.XML);
        getVariants().add(Variants.JSON);
    }

    @Override
    public Representation getRepresentation(final Variant variant) {
        final Request request = getRequest();
        Context context = getContext(request);

        Form options = getRequest().getResourceRef().getQueryAsForm();

        final String filterFileArg = options.getFirstValue("filter");
        final String bboxArg = options.getFirstValue("bbox");
        final String messageArg = options.getFirstValue("message");
        final boolean update = Boolean.valueOf(options.getFirstValue("update"));
        final boolean rebase = Boolean.valueOf(options.getFirstValue("rebase"));
        final String mappingFileArg = options.getFirstValue("mapping");

        checkArgSpec(filterFileArg != null ^ bboxArg != null || update,
                "You must specify a filter file or a bounding box");
        checkArgSpec((filterFileArg != null || bboxArg != null) ^ update,
                "Filters cannot be used when updating");

        checkArgSpec(context.index().isClean() && context.workingTree().isClean(),
                "Working tree and index are not clean");

        checkArgSpec(!rebase || update, "rebase switch can only be used when updating");

        final File filterFile = parseFile(filterFileArg);
        final File mappingFile = parseFile(mappingFileArg);
        final List<String> bbox = parseBbox(bboxArg);

        checkArgSpec(filterFile == null || filterFile.exists(),
                "The specified filter file does not exist");

        checkArgSpec(mappingFile == null || mappingFile.exists(),
                "The specified mapping file does not exist");

        AbstractGeoGigOp<Optional<OSMReport>> command;
        if (update) {
            command = context.command(OSMUpdateOp.class).setRebase(rebase).setMessage(messageArg)
                    .setAPIUrl(OSMUtils.DEFAULT_API_ENDPOINT);
        } else {
            command = context.command(OSMDownloadOp.class).setBbox(bbox).setFilterFile(filterFile)
                    .setMessage(messageArg).setMappingFile(mappingFile)
                    .setOsmAPIUrl(OSMUtils.DEFAULT_API_ENDPOINT);
        }

        AsyncCommand<Optional<OSMReport>> asyncCommand;

        URL repo = context.repository().getLocation();
        String description = String
                .format("osm download filter: %s, bbox: %s, mapping: %s, update: %s, rebase: %s, repository: %s",
                        filterFileArg, bboxArg, mappingFileArg, update, rebase, repo);
        asyncCommand = AsyncContext.get().run(command, description);

        final String rootPath = request.getRootRef().toString();
        MediaType mediaType = variant.getMediaType();
        Representation rep = new OSMReportRepresentation(mediaType, asyncCommand, rootPath);
        return rep;
    }

    private void checkArgSpec(boolean expression, String messageHeader) throws CommandSpecException {
        if (!expression) {
            throw usageMessage(messageHeader);
        }
    }

    @Nullable
    private File parseFile(@Nullable String filePath) throws CommandSpecException {
        if (Strings.isNullOrEmpty(filePath)) {
            return null;
        }
        File f = new File(filePath);
        return f;
    }

    @Nullable
    private List<String> parseBbox(@Nullable String bboxArg) {
        if (bboxArg == null) {
            return null;
        }
        List<String> bbox = Splitter.on(",").splitToList(bboxArg);
        checkArgSpec(bbox.size() == 4, "Invalid bbox format: " + bboxArg + ". Expected S,W,N,E");
        double s = parseOrdinate(bbox.get(0));
        double w = parseOrdinate(bbox.get(1));
        double n = parseOrdinate(bbox.get(2));
        double e = parseOrdinate(bbox.get(3));
        checkArgSpec(n >= s, "South ordinate must be less than or equal to North ordinate");
        checkArgSpec(e >= w, "East ordinate must be less than or equal to West ordinate");
        return bbox;
    }

    private double parseOrdinate(String ordinate) {
        try {
            return Double.parseDouble(ordinate);
        } catch (NumberFormatException e) {
            throw usageMessage("Invalid ordinate: " + ordinate);
        }
    }

    private CommandSpecException usageMessage(String messageHeader) throws CommandSpecException {
        String msg = messageHeader
                + "\nUsage: GET <repo context>/osm/download?<[filter=<filterfile>]|[bbox=S,W,N,E]>[&message=<commit message>]"
                + "[&mapping=<mapping file>][&update=true|false*][&rebase=true|false*]\n"
                + "Arguments:\n"
                + " * filter: Optional, or mandatory if {@code bbox} is not give. The filter file to use. Must exist in the server filesystem and contain an Overpass QL filter.\n"
                + " * bbox: Mandatory if {@code filter} is not given. The bounding box to use as filter, in WGS84 coordinates. Format: {@code <S>,<W>,<N>,<E>}.\n"
                + " * message: Message for the commit to create.\n"
                + " * update: Boolean. Default: false. Update the OSM data currently in the geogig repository.\n"
                + " * rebase: Boolean. Default: false. Use rebase instead of merge when updating. Can only be true of update is true.\n"
                + " * mapping: The file that contains the data mapping to use\n";
        throw new CommandSpecException(msg);
    }

}
TOP

Related Classes of org.locationtech.geogig.rest.osm.OsmDownloadWebOp

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.