/* Copyright (c) 2011 TOPP - www.openplans.org. All rights reserved.
 * This code is licensed under the LGPL 2.1 license, available at the root
 * application directory.
 */

package org.geogit.api.plumbing;

import org.geogit.api.AbstractGeoGitOp;
import org.geogit.api.ObjectId;
import org.geogit.api.RevObject;
import org.geogit.api.RevObject.TYPE;
import org.geogit.storage.StagingDatabase;

import com.google.common.base.Optional;
import com.google.inject.Inject;

/**
 * Resolves the reference given by a ref spec to the {@link RevObject} it finally points to,
 * dereferencing symbolic refs as necessary.
 * 
 * @see RevParse
 * @see ResolveObjectType
 */
public class RevObjectParse extends AbstractGeoGitOp<Optional<RevObject>> {

    private StagingDatabase indexDb;

    private ObjectId objectId;

    private String refSpec;

    /**
     * Constructs a new {@code RevObjectParse} operation with the given parameters.
     * 
     * @param indexDb the staging database
     */
    @Inject
    public RevObjectParse(StagingDatabase indexDb) {
        this.indexDb = indexDb;
    }

    /**
     * @param refSpec the ref spec to resolve
     * @return {@code this}
     */
    public RevObjectParse setRefSpec(final String refSpec) {
        this.objectId = null;
        this.refSpec = refSpec;
        return this;
    }

    /**
     * @param objectId the {@link ObjectId object id} to resolve
     * @return {@code this}
     */
    public RevObjectParse setObjectId(final ObjectId objectId) {
        this.refSpec = null;
        this.objectId = objectId;
        return this;
    }

    /**
     * @return the resolved object id
     * @throws IllegalArgumentException if the provided refspec doesn't resolve to any known object
     * @see RevObject
     */
    @Override
    public Optional<RevObject> call() throws IllegalArgumentException {
        return call(RevObject.class);
    }

    /**
     * @param clazz the base type of the parsed objects
     * @return the resolved object id
     * @see RevObject
     */
    public <T extends RevObject> Optional<T> call(Class<T> clazz) {
        final ObjectId resolvedObjectId;
        if (objectId == null) {
            Optional<ObjectId> parsed = command(RevParse.class).setRefSpec(refSpec).call();
            if (parsed.isPresent()) {
                resolvedObjectId = parsed.get();
            } else {
                resolvedObjectId = ObjectId.NULL;
            }
        } else {
            resolvedObjectId = objectId;
        }
        if (resolvedObjectId.isNull()) {
            return Optional.absent();
        }

        final TYPE type = command(ResolveObjectType.class).setObjectId(resolvedObjectId).call();
        RevObject revObject = indexDb.get(resolvedObjectId, type.binding());
        return Optional.of(clazz.cast(revObject));
    }
}

@@ -311,46 +311,8 @@
 ct;%0A
-import org.geogit.api.RevObject.TYPE;%0A
 impo
@@ -391,16 +391,61 @@
 tional;%0A
+import com.google.common.base.Preconditions;%0A
 import c
@@ -2614,70 +2614,41 @@
     
-final TYPE type = command(ResolveObjectType.class).setObjectId
+RevObject revObject = indexDb.get
 (res
@@ -2661,23 +2661,16 @@
 bjectId)
-.call()
 ;%0A      
@@ -2675,76 +2675,83 @@
     
-RevObject revObject = indexDb.get(resolvedObjectId, type.binding());
+Preconditions.checkArgument(clazz.isAssignableFrom(revObject.getClass()));%0A
 %0A   

cut the overhead of RevObjectParse by avoiding the call to ResolveObjectType