Package org.locationtech.geogig.api.hooks

Source Code of org.locationtech.geogig.api.hooks.GeoGigAPI

/* 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.api.hooks;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.locationtech.geogig.api.AbstractGeoGigOp;
import org.locationtech.geogig.api.FeatureBuilder;
import org.locationtech.geogig.api.NodeRef;
import org.locationtech.geogig.api.RevFeature;
import org.locationtech.geogig.api.RevFeatureType;
import org.locationtech.geogig.api.plumbing.ResolveFeatureType;
import org.locationtech.geogig.api.plumbing.RevObjectParse;
import org.locationtech.geogig.api.plumbing.diff.DiffEntry;
import org.locationtech.geogig.api.plumbing.diff.DiffEntry.ChangeType;
import org.locationtech.geogig.api.porcelain.DiffOp;
import org.locationtech.geogig.repository.Repository;
import org.opengis.feature.Feature;

import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.inject.Inject;

/**
* This class contains a facade for some of the most common operations to perform on a GeoGig
* repository. It is designed to be used mainly from hooks written in a scripting language supported
* by GeoGig, to give an easier and more detailed access to data and elements in the repository
*
*/
public class GeoGigAPI {

    private Repository repository;

    /**
     * @param repo the command locator to use when finding commands
     */
    @Inject
    public GeoGigAPI(Repository repository) {
        this.repository = repository;
    }

    /**
     * A convenience method to throw an exception indicating that the operation after a hook script
     * should not be executed
     *
     * @throws CannotRunGeogigOperationException
     */
    public void throwHookException(String msg) throws CannotRunGeogigOperationException {
        throw new CannotRunGeogigOperationException(msg);
    }

    /**
     * Returns an array with the features that are staged and ready to be commited. If noDeletions
     * is true, it doesn't include features to be removed, only those ones to be added or modified,
     * so it can be used to check the new data that will get commited into the repository
     *
     * @return
     */
    public Feature[] getFeaturesToCommit(String path, boolean noDeletions) {
        DiffOp diffOp = repository.command(DiffOp.class);
        diffOp.setCompareIndex(true);
        diffOp.setFilter(path);
        Iterator<DiffEntry> diffs = diffOp.call();
        List<Feature> list = Lists.newArrayList();
        while (diffs.hasNext()) {
            DiffEntry diff = diffs.next();
            if (!diff.changeType().equals(ChangeType.REMOVED) || !noDeletions) {
                RevFeature revFeature = repository.command(RevObjectParse.class)
                        .setObjectId(diff.newObjectId()).call(RevFeature.class).get();
                RevFeatureType revFeatureType = repository.command(RevObjectParse.class)
                        .setObjectId(diff.getNewObject().getMetadataId())
                        .call(RevFeatureType.class).get();
                FeatureBuilder builder = new FeatureBuilder(revFeatureType);
                list.add(builder.build(diff.getNewObject().name(), revFeature));
            }
        }
        return list.toArray(new Feature[0]);
    }

    public Feature[] getUnstagedFeatures(String path, boolean noDeletions) {
        Iterator<DiffEntry> diffs = repository.workingTree().getUnstaged(path);
        List<Feature> list = Lists.newArrayList();
        while (diffs.hasNext()) {
            DiffEntry diff = diffs.next();
            if (!diff.changeType().equals(ChangeType.REMOVED) || !noDeletions) {
                RevFeature revFeature = repository.command(RevObjectParse.class)
                        .setObjectId(diff.newObjectId()).call(RevFeature.class).get();
                RevFeatureType revFeatureType = repository.command(RevObjectParse.class)
                        .setObjectId(diff.getNewObject().getMetadataId())
                        .call(RevFeatureType.class).get();
                FeatureBuilder builder = new FeatureBuilder(revFeatureType);
                list.add(builder.build(diff.getNewObject().name(), revFeature));
            }
        }
        return list.toArray(new Feature[0]);
    }

    /**
     * Returns a feature from the Head of the repository, given its full path
     *
     * Returns null if the given path doesn't resolve to a feature
     *
     * @param path the path to the feature to return
     */
    public Feature getFeatureFromHead(String path) {
        String name = NodeRef.nodeFromPath(path);
        String refSpec = "HEAD:" + path;
        Optional<RevFeature> revFeature = repository.command(RevObjectParse.class)
                .setRefSpec(refSpec).call(RevFeature.class);
        if (revFeature.isPresent()) {
            RevFeatureType revFeatureType = repository.command(ResolveFeatureType.class)
                    .setRefSpec(refSpec).call().get();
            FeatureBuilder builder = new FeatureBuilder(revFeatureType);
            return builder.build(name, revFeature.get());
        } else {
            return null;
        }
    }

    /**
     * Returns a feature from the working tree of the repository, given its full path
     *
     * Returns null if the given path doesn't resolve to a feature
     *
     * @param path the path to the feature to return
     */
    public Feature getFeatureFromWorkingTree(String path) {
        String name = NodeRef.nodeFromPath(path);
        String refSpec = "WORK_HEAD:" + path;
        Optional<RevFeature> revFeature = repository.command(RevObjectParse.class)
                .setRefSpec(refSpec).call(RevFeature.class);
        if (revFeature.isPresent()) {
            RevFeatureType revFeatureType = repository.command(ResolveFeatureType.class)
                    .setRefSpec(refSpec).call().get();
            FeatureBuilder builder = new FeatureBuilder(revFeatureType);
            return builder.build(name, revFeature.get());
        } else {
            return null;
        }
    }

    /**
     * Runs a {@link AbstractGeoGigOp command} given by its class name and map of arguments.
     *
     * @param className the name of the {@link AbstractGeoGigOp command} to run
     * @param params expected an instanceo of {@code java.util.Map} or
     *        {@code sun.org.mozilla.javascript.internal.NativeObject} (which may or may not
     *        implement java.util.Map depending on the Java/JVM version)
     * @return the result of calling the named command with the given parameters.
     * @throws ClassNotFoundException if no command named after {@code className} exists
     */
    @SuppressWarnings("unchecked")
    public Object run(String className, Object params) throws ClassNotFoundException {
        Map<String, Object> paramsMap;
        if (params instanceof Map) {
            paramsMap = (Map<String, Object>) params;
        } else {
            paramsMap = java6NativeObjectToMap(params);
        }
        return runCommand(className, paramsMap);
    }

    /**
     * Converts an argument passed by a script to a Map.
     * <p>
     * This method is only needed when running with Oracle JDK 6, since its version of NativeObject
     * does not implement java.util.Map. Oracle JDK 7+ and OpenJDK6+ versions of NativeObject
     * already implement the java.util.Map interface.
     * <p>
     * Impl. detail: due to differences in package naming between oracle and
     */
    private Map<String, Object> java6NativeObjectToMap(Object params) {
        Map<String, Object> paramsMap = new HashMap<String, Object>();

        try {
            Class<?> NativeObject;
            Class<?> Scriptable;
            // Oracle JDK 6 location of the needed classes
            NativeObject = Class.forName("sun.org.mozilla.javascript.internal.NativeObject");
            Scriptable = Class.forName("sun.org.mozilla.javascript.internal.Scriptable");

            Method getPropertyIds = NativeObject.getMethod("getPropertyIds", Scriptable);
            Method getProperty = NativeObject.getMethod("getProperty", Scriptable, String.class);

            Object[] propertyIds = (Object[]) getPropertyIds.invoke(null, params);
            paramsMap = new HashMap<String, Object>();
            for (Object pid : propertyIds) {
                String key = String.valueOf(pid);
                Object value = getProperty.invoke(null, params, key);
                paramsMap.put(key, value);
            }
            return paramsMap;
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
    }

    /**
     * Runs the {@link AbstractGeoGigOp command} given by its {@code className} with the provided
     * {@code parameters}
     */
    private Object runCommand(String className, Map<String, Object> parameters)
            throws ClassNotFoundException {
        @SuppressWarnings("unchecked")
        Class<AbstractGeoGigOp<?>> clazz = (Class<AbstractGeoGigOp<?>>) Class.forName(className);

        AbstractGeoGigOp<?> operation = repository.command(clazz);
        @SuppressWarnings("unused")
        Map<String, Object> oldParams = Scripting.getParamMap(operation);
        Scripting.setParamMap(parameters, operation);
        return operation.call();
    }

}
TOP

Related Classes of org.locationtech.geogig.api.hooks.GeoGigAPI

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.