Package org.locationtech.geogig.geotools.data

Source Code of org.locationtech.geogig.geotools.data.GeogigTransactionState

/* 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:
* Gabriel Roldan (Boundless) - initial implementation
*/
package org.locationtech.geogig.geotools.data;

import java.io.IOException;
import java.util.Iterator;

import javax.annotation.Nullable;

import org.geotools.data.Transaction;
import org.geotools.data.Transaction.State;
import org.geotools.data.store.ContentEntry;
import org.locationtech.geogig.api.Context;
import org.locationtech.geogig.api.GeogigTransaction;
import org.locationtech.geogig.api.plumbing.DiffIndex;
import org.locationtech.geogig.api.plumbing.TransactionBegin;
import org.locationtech.geogig.api.plumbing.diff.DiffEntry;
import org.locationtech.geogig.api.porcelain.AddOp;
import org.locationtech.geogig.api.porcelain.CheckoutOp;
import org.locationtech.geogig.api.porcelain.CommitOp;
import org.locationtech.geogig.api.porcelain.ConflictsException;
import org.locationtech.geogig.api.porcelain.NothingToCommitException;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

/**
*
*/
class GeogigTransactionState implements State {

    /** VERSIONING_COMMIT_AUTHOR */
    static final String VERSIONING_COMMIT_AUTHOR = "VersioningCommitAuthor";

    /** VERSIONING_COMMIT_MESSAGE */
    static final String VERSIONING_COMMIT_MESSAGE = "VersioningCommitMessage";

    private ContentEntry entry;

    private GeogigTransaction geogigTx;

    private Transaction tx;

    /**
     * @param entry
     */
    public GeogigTransactionState(ContentEntry entry) {
        this.entry = entry;
    }

    public Optional<GeogigTransaction> getGeogigTransaction() {
        return Optional.fromNullable(this.geogigTx);
    }

    @Override
    public void setTransaction(@Nullable final Transaction transaction) {
        Preconditions.checkArgument(!Transaction.AUTO_COMMIT.equals(transaction));

        if (transaction != null && this.tx != null) {
            throw new IllegalStateException(
                    "New transaction set without closing old transaction first.");
        }
        this.tx = transaction;

        if (transaction == null) {
            // Transaction.removeState has been called (during
            // transaction.close())
            if (this.geogigTx != null) {
                // throw new
                // IllegalStateException("Transaction is attempting to "
                // + "close a non committed or aborted geogig transaction");
                geogigTx.abort();
            }
            this.geogigTx = null;
        } else {
            if (this.geogigTx != null) {
                geogigTx.abort();
            }
            GeoGigDataStore dataStore = (GeoGigDataStore) entry.getDataStore();
            Context commandLocator = dataStore.getCommandLocator(this.tx);
            this.geogigTx = commandLocator.command(TransactionBegin.class).call();
            // checkout the working branch
            final String workingBranch = dataStore.getOrFigureOutBranch();
            this.geogigTx.command(CheckoutOp.class).setForce(true).setSource(workingBranch).call();
        }
    }

    @Override
    public void addAuthorization(String AuthID) throws IOException {
        // not required
    }

    @Override
    public void commit() throws IOException {
        Preconditions.checkState(this.geogigTx != null);
        /*
         * This follows suite with the hack set on GeoSever's
         * org.geoserver.wfs.Transaction.getDatastoreTransaction()
         */
        final Optional<String> txUserName = getTransactionProperty(VERSIONING_COMMIT_AUTHOR);
        final Optional<String> fullName = getTransactionProperty("fullname");
        final Optional<String> email = getTransactionProperty("email");

        final String author = fullName.isPresent() ? fullName.get() : txUserName.orNull();
        String commitMessage = getTransactionProperty(VERSIONING_COMMIT_MESSAGE).orNull();

        this.geogigTx.command(AddOp.class).call();
        try {
            CommitOp commitOp = this.geogigTx.command(CommitOp.class);
            if (txUserName != null) {
                commitOp.setAuthor(author, email.orNull());
            }
            if (commitMessage == null) {
                commitMessage = composeDefaultCommitMessage();
            }
            commitOp.setMessage(commitMessage);
            commitOp.call();
        } catch (NothingToCommitException nochanges) {
            // ok
        }

        try {
            this.geogigTx.setAuthor(author, email.orNull()).commit();
        } catch (ConflictsException e) {
            // TODO: how should this be handled?
            this.geogigTx.abort();
        }

        this.geogigTx = null;
    }

    private Optional<String> getTransactionProperty(final String propName) {
        Object property = this.tx.getProperty(propName);
        if (property instanceof String) {
            return Optional.of((String) property);
        }
        return Optional.absent();
    }

    private String composeDefaultCommitMessage() {
        Iterator<DiffEntry> indexDiffs = this.geogigTx.command(DiffIndex.class).call();
        int added = 0, removed = 0, modified = 0;
        StringBuilder msg = new StringBuilder();
        while (indexDiffs.hasNext()) {
            DiffEntry entry = indexDiffs.next();
            switch (entry.changeType()) {
            case ADDED:
                added++;
                break;
            case MODIFIED:
                modified++;
                break;
            case REMOVED:
                removed++;
                break;
            }
            if ((added + removed + modified) < 10) {
                msg.append("\n ").append(entry.changeType().toString().toLowerCase()).append(' ')
                        .append(entry.newPath() == null ? entry.oldName() : entry.newPath());
            }
        }
        int count = added + removed + modified;
        if (count > 10) {
            msg.append("\n And ").append(count - 10).append(" more changes.");
        }
        StringBuilder title = new StringBuilder();
        if (added > 0) {
            title.append("added ").append(added);
        }
        if (modified > 0) {
            if (title.length() > 0) {
                title.append(", ");
            }
            title.append("modified ").append(modified);
        }
        if (removed > 0) {
            if (title.length() > 0) {
                title.append(", ");
            }
            title.append("removed ").append(removed);
        }
        if (count > 0) {
            title.append(" features via unversioned legacy client.\n");
        }
        msg.insert(0, title);
        return msg.toString();
    }

    @Override
    public void rollback() throws IOException {
        Preconditions.checkState(this.geogigTx != null);
        this.geogigTx.abort();
        this.geogigTx = null;
    }

}
TOP

Related Classes of org.locationtech.geogig.geotools.data.GeogigTransactionState

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.