/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.cache.options;

import junit.framework.TestCase;
import junit.framework.Assert;
import org.jboss.cache.TreeCache;
import org.jboss.cache.Fqn;
import org.jboss.cache.OptimisticTreeNode;
import org.jboss.cache.config.Option;
import org.jboss.cache.optimistic.DataVersion;
import org.jboss.cache.optimistic.DefaultDataVersion;

import javax.transaction.TransactionManager;

/**
 * Tests the passing in of explicit {@see DataVersion} instances when using optimistic locking.
 *
 * @author <a href="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
 */
public class ExplicitVersionsTest extends TestCase
{

    private TreeCache cache;
    private Fqn fqn = Fqn.fromString("/a");
    private String key = "key";
    private Option option = new Option();

    protected void setUp() throws Exception
    {
        if (cache != null) tearDown();
        cache = new TreeCache();
        cache.setCacheMode( TreeCache.LOCAL );
        cache.setNodeLockingScheme("OPTIMISTIC");
        cache.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
        cache.startService();
    }

    protected void tearDown()
    {
        if (cache != null)
        {
            cache.stopService();
            cache = null;
        }
    }

    public void testSimplePut() throws Exception
    {
        DataVersion version = new TestVersion("99");
        option.setDataVersion( version );
        cache.put(fqn, key, "value", option);

        //now retrieve the data from the cache.
        Assert.assertEquals("value", cache.get(fqn,key));

        // get a hold of the node
        OptimisticTreeNode node = (OptimisticTreeNode) cache.get(fqn);
        DataVersion versionFromCache = node.getVersion();

        Assert.assertEquals(TestVersion.class, versionFromCache.getClass());
        Assert.assertEquals("99", ((TestVersion) versionFromCache).getInternalVersion());
    }

    public void testFailingPut() throws Exception
    {
        DataVersion version = new TestVersion("99");
        option.setDataVersion(version);
        cache.put(fqn, key, "value", option);

        version = new TestVersion("25");
        option.setDataVersion(version);
        TransactionManager mgr = cache.getTransactionManager();
        mgr.begin();
        cache.put(fqn, key, "value2", option);
        try
        {
            mgr.commit();
            Assert.assertTrue("expected to fail", false);
        }
        catch (Exception e)
        {
            // should fail.
            Assert.assertTrue("expected to fail", true);
        }
    }

    public void testIncompatibleVersionTypes() throws Exception
    {
        DataVersion version = new TestVersion("99");
        option.setDataVersion(version);
        cache.put(fqn, key, "value", option);
        TransactionManager mgr = cache.getTransactionManager();
        mgr.begin();
        option.setDataVersion(new DefaultDataVersion(777));
        cache.put(fqn, key, "value2", option);
        try
        {
            // this call will use implicit versioning and will hence fail.
            mgr.commit();
            Assert.assertTrue("expected to fail", false);
        }
        catch (Exception e)
        {
            // should fail.
            Assert.assertTrue("expected to fail", true);
        }
    }

}

class TestVersion implements DataVersion
{
    private String myVersion;

    public TestVersion(String version)
    {
        myVersion = version;
    }

    public String getInternalVersion()
    {
        return myVersion;
    }

    public void setInternalVersion(String version)
    {
        myVersion = version;
    }

    public boolean newerThan(DataVersion other)
    {
        if (other instanceof TestVersion)
        {
            int myInt = Integer.parseInt( myVersion );
            int otherInt = Integer.parseInt( ((TestVersion) other).getInternalVersion() );
            return myInt > otherInt;
        }
        else throw new IllegalArgumentException("version type mismatch");
    }
}