Package org.locationtech.geogig.cli.plumbing

Source Code of org.locationtech.geogig.cli.plumbing.DiffTree

/* 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.cli.plumbing;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.locationtech.geogig.api.GeoGIG;
import org.locationtech.geogig.api.NodeRef;
import org.locationtech.geogig.api.RevFeature;
import org.locationtech.geogig.api.RevFeatureType;
import org.locationtech.geogig.api.RevObject;
import org.locationtech.geogig.api.plumbing.DiffFeature;
import org.locationtech.geogig.api.plumbing.RevObjectParse;
import org.locationtech.geogig.api.plumbing.diff.AttributeDiff;
import org.locationtech.geogig.api.plumbing.diff.AttributeDiff.TYPE;
import org.locationtech.geogig.api.plumbing.diff.DiffEntry;
import org.locationtech.geogig.api.plumbing.diff.DiffEntry.ChangeType;
import org.locationtech.geogig.api.plumbing.diff.FeatureDiff;
import org.locationtech.geogig.cli.AbstractCommand;
import org.locationtech.geogig.cli.CLICommand;
import org.locationtech.geogig.cli.CommandFailedException;
import org.locationtech.geogig.cli.GeogigCLI;
import org.locationtech.geogig.cli.annotation.ReadOnly;
import org.locationtech.geogig.storage.text.TextValueSerializer;
import org.opengis.feature.type.PropertyDescriptor;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.base.Optional;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
* Plumbing command to shows changes between trees
*
* @see DiffTree
*/
@ReadOnly
@Parameters(commandNames = "diff-tree", commandDescription = "Show changes between trees")
public class DiffTree extends AbstractCommand implements CLICommand {

    private static final String LINE_BREAK = System.getProperty("line.separator");

    @Parameter(description = "[<treeish> [<treeish>]] [-- <path>...]", arity = 2)
    private List<String> refSpec = Lists.newArrayList();

    @Parameter(names = "--", hidden = true, variableArity = true)
    private List<String> paths = Lists.newArrayList();

    @Parameter(names = "--describe", description = "add description of versions for each modified element")
    private boolean describe;

    @Parameter(names = "--tree-stats", description = "shows only statistics of modified elements in each changed tree")
    private boolean treeStats;

    /**
     * Executes the diff-tree command with the specified options.
     */
    @Override
    protected void runInternal(GeogigCLI cli) throws IOException {
        if (refSpec.size() > 2) {
            throw new CommandFailedException("Tree refspecs list is too long :" + refSpec);
        }

        if (treeStats && describe) {
            throw new CommandFailedException(
                    "Cannot use --describe and --tree-stats simultaneously");
        }

        GeoGIG geogig = cli.getGeogig();

        org.locationtech.geogig.api.plumbing.DiffTree diff = geogig
                .command(org.locationtech.geogig.api.plumbing.DiffTree.class);

        String oldVersion = resolveOldVersion();
        String newVersion = resolveNewVersion();

        diff.setOldVersion(oldVersion).setNewVersion(newVersion);

        Iterator<DiffEntry> diffEntries;
        if (paths.isEmpty()) {
            diffEntries = diff.setProgressListener(cli.getProgressListener()).call();
        } else {
            diffEntries = Iterators.emptyIterator();
            for (String path : paths) {
                Iterator<DiffEntry> moreEntries = diff.setPathFilter(path)
                        .setProgressListener(cli.getProgressListener()).call();
                diffEntries = Iterators.concat(diffEntries, moreEntries);
            }
        }

        DiffEntry diffEntry;
        HashMap<String, Long[]> stats = Maps.newHashMap();
        while (diffEntries.hasNext()) {
            diffEntry = diffEntries.next();
            StringBuilder sb = new StringBuilder();
            String path = diffEntry.newPath() != null ? diffEntry.newPath() : diffEntry.oldPath();

            if (describe) {
                sb.append(diffEntry.changeType().toString().charAt(0)).append(' ').append(path)
                        .append(LINE_BREAK);

                if (diffEntry.changeType() == ChangeType.MODIFIED) {
                    FeatureDiff featureDiff = geogig.command(DiffFeature.class)
                            .setNewVersion(Suppliers.ofInstance(diffEntry.getNewObject()))
                            .setOldVersion(Suppliers.ofInstance(diffEntry.getOldObject())).call();
                    Map<PropertyDescriptor, AttributeDiff> diffs = featureDiff.getDiffs();
                    HashSet<PropertyDescriptor> diffDescriptors = Sets.newHashSet(diffs.keySet());
                    NodeRef noderef = diffEntry.changeType() != ChangeType.REMOVED ? diffEntry
                            .getNewObject() : diffEntry.getOldObject();
                    RevFeatureType featureType = geogig.command(RevObjectParse.class)
                            .setObjectId(noderef.getMetadataId()).call(RevFeatureType.class).get();
                    Optional<RevObject> obj = geogig.command(RevObjectParse.class)
                            .setObjectId(noderef.objectId()).call();
                    RevFeature feature = (RevFeature) obj.get();
                    ImmutableList<Optional<Object>> values = feature.getValues();
                    ImmutableList<PropertyDescriptor> descriptors = featureType.sortedDescriptors();
                    int idx = 0;
                    for (PropertyDescriptor descriptor : descriptors) {
                        if (diffs.containsKey(descriptor)) {
                            AttributeDiff ad = diffs.get(descriptor);
                            sb.append(ad.getType().toString().charAt(0) + " "
                                    + descriptor.getName().toString() + LINE_BREAK);
                            if (!ad.getType().equals(TYPE.ADDED)) {
                                Object value = ad.getOldValue().orNull();
                                sb.append(TextValueSerializer.asString(Optional.fromNullable(value)));
                                sb.append(LINE_BREAK);
                            }
                            if (!ad.getType().equals(TYPE.REMOVED)) {
                                Object value = ad.getNewValue().orNull();
                                sb.append(TextValueSerializer.asString(Optional.fromNullable(value)));
                                sb.append(LINE_BREAK);
                            }
                            diffDescriptors.remove(descriptor);
                        } else {
                            sb.append("U ").append(descriptor.getName().toString())
                                    .append(LINE_BREAK);
                            sb.append(TextValueSerializer.asString(values.get(idx))).append(
                                    LINE_BREAK);
                        }
                        idx++;
                    }
                    for (PropertyDescriptor descriptor : diffDescriptors) {
                        AttributeDiff ad = diffs.get(descriptor);
                        sb.append(ad.getType().toString().charAt(0) + " "
                                + descriptor.getName().toString() + LINE_BREAK);
                        if (!ad.getType().equals(TYPE.ADDED)) {
                            Object value = ad.getOldValue().orNull();
                            sb.append(TextValueSerializer.asString(Optional.fromNullable(value)));
                            sb.append(LINE_BREAK);
                        }
                        if (!ad.getType().equals(TYPE.REMOVED)) {
                            Object value = ad.getNewValue().orNull();
                            sb.append(TextValueSerializer.asString(Optional.fromNullable(value)));
                            sb.append(LINE_BREAK);
                        }
                    }
                } else {
                    NodeRef noderef = diffEntry.changeType() == ChangeType.ADDED ? diffEntry
                            .getNewObject() : diffEntry.getOldObject();
                    RevFeatureType featureType = geogig.command(RevObjectParse.class)
                            .setObjectId(noderef.getMetadataId()).call(RevFeatureType.class).get();
                    Optional<RevObject> obj = geogig.command(RevObjectParse.class)
                            .setObjectId(noderef.objectId()).call();
                    RevFeature feature = (RevFeature) obj.get();
                    ImmutableList<Optional<Object>> values = feature.getValues();
                    int i = 0;
                    for (Optional<Object> value : values) {
                        sb.append(diffEntry.changeType().toString().charAt(0));
                        sb.append(' ');
                        sb.append(featureType.sortedDescriptors().get(i).getName().toString());
                        sb.append(LINE_BREAK);
                        sb.append(TextValueSerializer.asString(value));
                        sb.append(LINE_BREAK);
                        i++;
                    }
                    sb.append(LINE_BREAK);
                }
                sb.append(LINE_BREAK);
                cli.getConsole().println(sb.toString());
            } else if (treeStats) {
                String parent = NodeRef.parentPath(path);
                if (!stats.containsKey(parent)) {
                    stats.put(parent, new Long[] { 0l, 0l, 0l });
                }
                Long[] counts = stats.get(parent);
                if (diffEntry.changeType() == ChangeType.ADDED) {
                    counts[0]++;
                } else if (diffEntry.changeType() == ChangeType.REMOVED) {
                    counts[1]++;
                } else if (diffEntry.changeType() == ChangeType.MODIFIED) {
                    counts[2]++;
                }
            }

            else {
                sb.append(path).append(' ');
                sb.append(diffEntry.oldObjectId().toString());
                sb.append(' ');
                sb.append(diffEntry.newObjectId().toString());
                cli.getConsole().println(sb.toString());
            }

        }
        if (treeStats) {
            for (String path : stats.keySet()) {
                StringBuffer sb = new StringBuffer();
                sb.append(path);
                Long[] counts = stats.get(path);
                for (int i = 0; i < counts.length; i++) {
                    sb.append(" " + counts[i].toString());
                }
                cli.getConsole().println(sb.toString());
            }
        }
    }

    private String resolveOldVersion() {
        return refSpec.size() > 0 ? refSpec.get(0) : "WORK_HEAD";
    }

    private String resolveNewVersion() {
        return refSpec.size() > 1 ? refSpec.get(1) : "STAGE_HEAD";
    }

}
TOP

Related Classes of org.locationtech.geogig.cli.plumbing.DiffTree

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.