Package org.locationtech.geogig.osm.internal

Source Code of org.locationtech.geogig.osm.internal.OSMMapOp

/* Copyright (c) 2013-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:
* Victor Olaya (Boundless) - initial implementation
*/
package org.locationtech.geogig.osm.internal;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;

import org.locationtech.geogig.api.AbstractGeoGigOp;
import org.locationtech.geogig.api.FeatureBuilder;
import org.locationtech.geogig.api.NodeRef;
import org.locationtech.geogig.api.ObjectId;
import org.locationtech.geogig.api.RevFeature;
import org.locationtech.geogig.api.RevFeatureTypeImpl;
import org.locationtech.geogig.api.RevTree;
import org.locationtech.geogig.api.plumbing.LsTreeOp;
import org.locationtech.geogig.api.plumbing.LsTreeOp.Strategy;
import org.locationtech.geogig.api.plumbing.RevObjectParse;
import org.locationtech.geogig.api.plumbing.RevParse;
import org.locationtech.geogig.api.porcelain.AddOp;
import org.locationtech.geogig.api.porcelain.CommitOp;
import org.locationtech.geogig.osm.internal.log.OSMMappingLogEntry;
import org.locationtech.geogig.osm.internal.log.WriteOSMMappingEntries;
import org.opengis.feature.Feature;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;

/**
* Creates new data in a geogig repository, based on the current OSM data in the repository and a
* mapping that defines the schema to use for creating new features and the destination trees.
*
* The source data used is the working tree data in the "node" and "way" trees.
*
*/
public class OSMMapOp extends AbstractGeoGigOp<RevTree> {

    /**
     * The mapping to use
     */
    private Mapping mapping;

    /**
     * The message to use for the commit to create
     */
    private String message;

    /**
     * Sets the mapping to use
     *
     * @param mapping the mapping to use
     * @return {@code this}
     */
    public OSMMapOp setMapping(Mapping mapping) {
        this.mapping = mapping;
        return this;
    }

    /**
     * Sets the message to use for the commit that is created
     *
     * @param message the commit message
     * @return {@code this}
     */
    public OSMMapOp setMessage(String message) {
        this.message = message;
        return this;
    }

    @Override
    protected RevTree _call() {

        checkNotNull(mapping);

        long staged = index().countStaged(null).count();
        long unstaged = workingTree().countUnstaged(null).count();
        Preconditions.checkState((staged == 0 && unstaged == 0),
                "You must have a clean working tree and index to perform a mapping.");

        ObjectId oldTreeId = workingTree().getTree().getId();

        Iterator<Feature> nodes;
        if (mapping.canUseNodes()) {
            nodes = getFeatures("WORK_HEAD:node");
        } else {
            nodes = Iterators.emptyIterator();
        }
        Iterator<Feature> ways;
        if (mapping.canUseWays()) {
            ways = getFeatures("WORK_HEAD:way");
        } else {
            ways = Iterators.emptyIterator();
        }
        Iterator<Feature> iterator = Iterators.concat(nodes, ways);

        if (iterator.hasNext()) {
            FeatureMapFlusher insertsByParent = new FeatureMapFlusher(workingTree());
            while (iterator.hasNext()) {
                Feature feature = iterator.next();
                List<MappedFeature> mappedFeatures = mapping.map(feature);
                if (!mappedFeatures.isEmpty()) {
                    for (MappedFeature mapped : mappedFeatures) {
                        String path = mapped.getPath();
                        insertsByParent.put(path, mapped);
                    }
                }
            }
            insertsByParent.flushAll();

            ObjectId newTreeId = workingTree().getTree().getId();
            // If the mapping generates the same mapped features that already exist, we do nothing
            if (!newTreeId.equals(oldTreeId)) {
                command(AddOp.class).call();
                command(CommitOp.class).setMessage(message).call();
                command(WriteOSMMappingEntries.class).setMapping(mapping)
                        .setMappingLogEntry(new OSMMappingLogEntry(oldTreeId, newTreeId)).call();
            }

        }

        return workingTree().getTree();

    }

    private Iterator<Feature> getFeatures(String ref) {
        Optional<ObjectId> id = command(RevParse.class).setRefSpec(ref).call();
        if (!id.isPresent()) {
            return Iterators.emptyIterator();
        }
        LsTreeOp op = command(LsTreeOp.class).setStrategy(Strategy.DEPTHFIRST_ONLY_FEATURES)
                .setReference(ref);

        Iterator<NodeRef> iterator = op.call();

        Function<NodeRef, Feature> nodeRefToFeature = new Function<NodeRef, Feature>() {

            private final Map<String, FeatureBuilder> builders = //
            ImmutableMap.<String, FeatureBuilder> of(//
                    OSMUtils.NODE_TYPE_NAME, //
                    new FeatureBuilder(RevFeatureTypeImpl.build(OSMUtils.nodeType())), //
                    OSMUtils.WAY_TYPE_NAME,//
                    new FeatureBuilder(RevFeatureTypeImpl.build(OSMUtils.wayType())));

            private final RevObjectParse parseCommand = command(RevObjectParse.class);

            @Override
            @Nullable
            public Feature apply(@Nullable NodeRef ref) {
                RevFeature revFeature = parseCommand.setObjectId(ref.objectId())
                        .call(RevFeature.class).get();
                final String parentPath = ref.getParentPath();
                FeatureBuilder featureBuilder = builders.get(parentPath);
                String fid = ref.name();
                Feature feature = featureBuilder.build(fid, revFeature);
                return feature;
            }

        };
        return Iterators.transform(iterator, nodeRefToFeature);
    }
}
TOP

Related Classes of org.locationtech.geogig.osm.internal.OSMMapOp

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.