/*
 * Copyright (c) 2010-2013, 2015 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.emf.cdo.tests;

import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.revision.CDOAllRevisionsProvider;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.server.IRepository;
import org.eclipse.emf.cdo.server.IStore;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.session.CDOSessionConfiguration;
import org.eclipse.emf.cdo.session.CDOSessionConfigurationFactory;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.spi.workspace.InternalCDOWorkspace;
import org.eclipse.emf.cdo.tests.config.IRepositoryConfig;
import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Requires;
import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Skips;
import org.eclipse.emf.cdo.tests.model1.Customer;
import org.eclipse.emf.cdo.tests.model1.OrderDetail;
import org.eclipse.emf.cdo.tests.model1.Product1;
import org.eclipse.emf.cdo.tests.model1.SalesOrder;
import org.eclipse.emf.cdo.tests.model1.VAT;
import org.eclipse.emf.cdo.tests.util.TestSessionConfiguration;
import org.eclipse.emf.cdo.transaction.CDOMerger.ConflictException;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.workspace.CDOWorkspace;
import org.eclipse.emf.cdo.workspace.CDOWorkspaceBase;
import org.eclipse.emf.cdo.workspace.CDOWorkspaceConfiguration;
import org.eclipse.emf.cdo.workspace.CDOWorkspaceUtil;

import org.eclipse.net4j.jvm.JVMUtil;
import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.spi.cdo.DefaultCDOMerger;
import org.eclipse.emf.spi.cdo.DefaultCDOMerger.Conflict;

import java.io.File;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author Eike Stepper
 */
@Requires({ IRepositoryConfig.CAPABILITY_AUDITING, IRepositoryConfig.CAPABILITY_UUIDS })
@Skips("DB.ranges")
public class WorkspaceTest extends AbstractCDOTest
{
  private static final String RESOURCE = "/test1";

  private static final int PRODUCTS = 5;

  private static final int CUSTOMERS = 2;

  private static final int SALES_ORDERS_PER_CUSTOMER = 1;

  private static final int SALES_ORDERS = CUSTOMERS * SALES_ORDERS_PER_CUSTOMER;

  private static final int ORDER_DETAILS = SALES_ORDERS * PRODUCTS;

  private List<CDOWorkspace> workspaces = new ArrayList<CDOWorkspace>();

  private CDOTransaction transaction;

  private List<Product1> products;

  private List<Customer> customers;

  private List<SalesOrder> salesOrders;

  private List<OrderDetail> orderDetails;

  private int totalObjects;

  private IStore localStore;

  @Override
  protected void doSetUp() throws Exception
  {
    super.doSetUp();
    skipStoreWithoutRawAccess();
    skipStoreWithoutHandleRevisions();

    CDOSession session = openSession();
    transaction = session.openTransaction();

    products = new ArrayList<Product1>();
    customers = new ArrayList<Customer>();
    orderDetails = new ArrayList<OrderDetail>();
    salesOrders = new ArrayList<SalesOrder>();

    createTestSet(transaction);
    assertEquals(PRODUCTS, products.size());
    assertEquals(CUSTOMERS, customers.size());
    assertEquals(SALES_ORDERS, salesOrders.size());
    assertEquals(ORDER_DETAILS, orderDetails.size());

    JVMUtil.prepareContainer(getClientContainer());
    localStore = createLocalStore();
  }

  @Override
  protected void doTearDown() throws Exception
  {
    disableConsole();
    for (CDOWorkspace workspace : workspaces)
    {
      IOUtil.closeSilent(workspace);
    }

    workspaces.clear();
    workspaces = null;
    transaction = null;
    products = null;
    customers = null;
    salesOrders = null;
    orderDetails = null;
    localStore = null;
    super.doTearDown();
  }

  @Override
  public synchronized Map<String, Object> getTestProperties()
  {
    Map<String, Object> map = super.getTestProperties();
    map.put(IRepository.Props.ENSURE_REFERENTIAL_INTEGRITY, "false");
    return map;
  }

  @CleanRepositoriesBefore(reason = "Object counting")
  public void testCheckout() throws Exception
  {
    checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertEquals(2 + totalObjects, dumpLocalStore(null)); // Root resource + test folder + totalObjects
  }

  public void testReadObjects() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOView view = workspace.openView();
    CDOResource resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects, dumpObjects(null, resource));
  }

  public void testModifyObjects() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED_" + product.getName());
      }
    }

    assertEquals(true, transaction.isDirty());
    assertEquals(PRODUCTS, transaction.getDirtyObjects().size());

    transaction.commit();
    assertEquals(false, transaction.isDirty());
    assertEquals(0, transaction.getDirtyObjects().size());

    clearCache(transaction.getSession().getRevisionManager());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects, dumpObjects(null, resource));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        assertEquals(true, product.getName().startsWith("MODIFIED_"));
      }
    }
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testAddObjects() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    assertEquals(true, transaction.isDirty());
    assertEquals(1, transaction.getDirtyObjects().size());
    assertEquals(PRODUCTS, transaction.getNewObjects().size());

    transaction.commit();
    assertEquals(false, transaction.isDirty());
    assertEquals(0, transaction.getDirtyObjects().size());
    assertEquals(0, transaction.getNewObjects().size());

    clearCache(transaction.getSession().getRevisionManager());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects + PRODUCTS, dumpObjects("--> ", resource));
  }

  public void testDetachObjects() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        ((SalesOrder)object).getOrderDetails().clear();
      }

      if (object instanceof Product1)
      {
        ((Product1)object).getOrderDetails().clear();
      }
    }

    assertEquals(true, transaction.isDirty());
    assertEquals(SALES_ORDERS + PRODUCTS, transaction.getDirtyObjects().size());
    assertEquals(ORDER_DETAILS, transaction.getDetachedObjects().size());

    transaction.commit();
    assertEquals(false, transaction.isDirty());
    assertEquals(0, transaction.getDirtyObjects().size());
    assertEquals(0, transaction.getDetachedObjects().size());

    clearCache(transaction.getSession().getRevisionManager());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects - ORDER_DETAILS, dumpObjects(null, resource));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        if (!((SalesOrder)object).getOrderDetails().isEmpty())
        {
          fail("All order details should be detached");
        }
      }
    }
  }

  public void testModifyObjects2() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED_" + product.getName());
      }
    }

    assertEquals(true, transaction.isDirty());
    assertEquals(PRODUCTS, transaction.getDirtyObjects().size());

    transaction.commit();
    assertEquals(false, transaction.isDirty());
    assertEquals(0, transaction.getDirtyObjects().size());

    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED2_" + product.getName());
      }
    }

    assertEquals(true, transaction.isDirty());
    assertEquals(PRODUCTS, transaction.getDirtyObjects().size());

    transaction.commit();
    assertEquals(false, transaction.isDirty());
    assertEquals(0, transaction.getDirtyObjects().size());

    clearCache(transaction.getSession().getRevisionManager());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects, dumpObjects(null, resource));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        assertEquals(true, product.getName().startsWith("MODIFIED2_"));
      }
    }
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testAddObjects2() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    assertEquals(true, transaction.isDirty());
    assertEquals(1, transaction.getDirtyObjects().size());
    assertEquals(PRODUCTS, transaction.getNewObjects().size());

    transaction.commit();
    assertEquals(false, transaction.isDirty());
    assertEquals(0, transaction.getDirtyObjects().size());
    assertEquals(0, transaction.getNewObjects().size());

    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    assertEquals(true, transaction.isDirty());
    assertEquals(1, transaction.getDirtyObjects().size());
    assertEquals(PRODUCTS, transaction.getNewObjects().size());

    transaction.commit();
    assertEquals(false, transaction.isDirty());
    assertEquals(0, transaction.getDirtyObjects().size());
    assertEquals(0, transaction.getNewObjects().size());

    clearCache(transaction.getSession().getRevisionManager());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects + 2 * PRODUCTS, dumpObjects("--> ", resource));
  }

  public void testDetachObjects2() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        ((SalesOrder)object).getOrderDetails().clear();
      }

      if (object instanceof Product1)
      {
        ((Product1)object).getOrderDetails().clear();
      }
    }

    assertEquals(true, transaction.isDirty());
    assertEquals(SALES_ORDERS + PRODUCTS, transaction.getDirtyObjects().size());
    assertEquals(ORDER_DETAILS, transaction.getDetachedObjects().size());

    transaction.commit();
    assertEquals(false, transaction.isDirty());
    assertEquals(0, transaction.getDirtyObjects().size());
    assertEquals(0, transaction.getDetachedObjects().size());

    for (Iterator<EObject> it = resource.getContents().iterator(); it.hasNext();)
    {
      EObject object = it.next();
      if (object instanceof SalesOrder)
      {
        it.remove();
      }

      if (object instanceof Customer)
      {
        ((Customer)object).getSalesOrders().clear();
      }
    }

    assertEquals(true, transaction.isDirty());
    assertEquals(1 + CUSTOMERS, transaction.getDirtyObjects().size());
    assertEquals(SALES_ORDERS, transaction.getDetachedObjects().size());

    transaction.commit();
    assertEquals(false, transaction.isDirty());
    assertEquals(0, transaction.getDirtyObjects().size());
    assertEquals(0, transaction.getDetachedObjects().size());

    clearCache(transaction.getSession().getRevisionManager());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects - ORDER_DETAILS - SALES_ORDERS, dumpObjects(null, resource));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        if (!((SalesOrder)object).getOrderDetails().isEmpty())
        {
          fail("All order details should be detached");
        }
      }

      if (object instanceof Customer)
      {
        if (!((Customer)object).getSalesOrders().isEmpty())
        {
          fail("All sales orders should be detached");
        }
      }
    }
  }

  public void testLocalChangesAfterModify() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED_" + product.getName());
      }
    }

    transaction.commit();

    CDOChangeSetData changes = workspace.getLocalChanges();
    assertEquals(0, changes.getNewObjects().size());
    assertEquals(PRODUCTS, changes.getChangedObjects().size());
    assertEquals(0, changes.getDetachedObjects().size());
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testLocalChangesAfterAdd() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    transaction.commit();

    CDOChangeSetData changes = workspace.getLocalChanges();
    assertEquals(PRODUCTS, changes.getNewObjects().size());
    assertEquals(1, changes.getChangedObjects().size());
    assertEquals(0, changes.getDetachedObjects().size());
  }

  public void testLocalChangesAfterDetach() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        ((SalesOrder)object).getOrderDetails().clear();
      }

      if (object instanceof Product1)
      {
        ((Product1)object).getOrderDetails().clear();
      }
    }

    transaction.commit();

    CDOChangeSetData changes = workspace.getLocalChanges();
    assertEquals(0, changes.getNewObjects().size());
    assertEquals(SALES_ORDERS + PRODUCTS, changes.getChangedObjects().size());
    assertEquals(ORDER_DETAILS, changes.getDetachedObjects().size());
  }

  public void testLocalChangesAfterModify2() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED_" + product.getName());
      }
    }

    transaction.commit();

    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED2_" + product.getName());
      }
    }

    transaction.commit();

    CDOChangeSetData changes = workspace.getLocalChanges();
    assertEquals(0, changes.getNewObjects().size());
    assertEquals(PRODUCTS, changes.getChangedObjects().size());
    assertEquals(0, changes.getDetachedObjects().size());
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testLocalChangesAfterAdd2() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    transaction.commit();

    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    transaction.commit();

    CDOChangeSetData changes = workspace.getLocalChanges();
    assertEquals(2 * PRODUCTS, changes.getNewObjects().size());
    assertEquals(1, changes.getChangedObjects().size());
    assertEquals(0, changes.getDetachedObjects().size());
  }

  public void testLocalChangesAfterDetach2() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        ((SalesOrder)object).getOrderDetails().clear();
      }

      if (object instanceof Product1)
      {
        ((Product1)object).getOrderDetails().clear();
      }
    }

    transaction.commit();

    for (Iterator<EObject> it = resource.getContents().iterator(); it.hasNext();)
    {
      EObject object = it.next();
      if (object instanceof SalesOrder)
      {
        it.remove();
      }

      if (object instanceof Customer)
      {
        ((Customer)object).getSalesOrders().clear();
      }
    }

    transaction.commit();

    CDOChangeSetData changes = workspace.getLocalChanges();
    assertEquals(0, changes.getNewObjects().size());
    assertEquals(1 + CUSTOMERS + PRODUCTS, changes.getChangedObjects().size());
    assertEquals(ORDER_DETAILS + SALES_ORDERS, changes.getDetachedObjects().size());
  }

  public void testCheckinAfterModify() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED_" + product.getName());
      }
    }

    transaction.commit();

    CDOCommitInfo info = workspace.checkin();
    assertEquals(0, info.getNewObjects().size());
    assertEquals(PRODUCTS, info.getChangedObjects().size());
    assertEquals(0, info.getDetachedObjects().size());

    CDOWorkspaceBase base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testCheckinAfterAdd() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    IOUtil.ERR().println("Checkout done");

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    transaction.commit();

    CDOCommitInfo info = workspace.checkin();
    assertEquals(PRODUCTS, info.getNewObjects().size());
    assertEquals(1, info.getChangedObjects().size());
    assertEquals(0, info.getDetachedObjects().size());

    CDOWorkspaceBase base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testCheckinAfterAddExt() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    IOUtil.ERR().println("Checkout done");

    {
      CDOTransaction transaction = workspace.openTransaction();
      CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
      for (int i = 0; i < PRODUCTS; i++)
      {
        resource.getContents().add(createProduct(i));
      }

      transaction.commit();
      transaction.close();
    }

    {
      CDOTransaction transaction = workspace.openTransaction();
      CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
      for (int i = 0; i < PRODUCTS; i++)
      {
        resource.getContents().add(createProduct(i));
      }

      transaction.commit();
      transaction.close();
    }

    workspace.checkin();
    // workspace.update(null);

    {
      CDOTransaction transaction = workspace.openTransaction();
      CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
      for (int i = 0; i < PRODUCTS; i++)
      {
        resource.getContents().add(createProduct(i));
      }

      transaction.commit();
      transaction.close();
    }

    workspace.checkin();
  }

  public void testCheckinAfterDetach() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        ((SalesOrder)object).getOrderDetails().clear();
      }

      if (object instanceof Product1)
      {
        ((Product1)object).getOrderDetails().clear();
      }
    }

    transaction.commit();

    CDOCommitInfo info = workspace.checkin();
    assertEquals(0, info.getNewObjects().size());
    assertEquals(SALES_ORDERS + PRODUCTS, info.getChangedObjects().size());
    assertEquals(ORDER_DETAILS, info.getDetachedObjects().size());

    CDOWorkspaceBase base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());
  }

  public void testCheckinAfterModify2() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED_" + product.getName());
      }
    }

    transaction.commit();

    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED2_" + product.getName());
      }
    }

    transaction.commit();

    CDOCommitInfo info = workspace.checkin();
    assertEquals(0, info.getNewObjects().size());
    assertEquals(PRODUCTS, info.getChangedObjects().size());
    assertEquals(0, info.getDetachedObjects().size());

    CDOWorkspaceBase base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testCheckinAfterAdd2() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    transaction.commit();

    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    transaction.commit();

    CDOCommitInfo info = workspace.checkin();
    assertEquals(2 * PRODUCTS, info.getNewObjects().size());
    assertEquals(1, info.getChangedObjects().size());
    assertEquals(0, info.getDetachedObjects().size());

    CDOWorkspaceBase base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());
  }

  public void testCheckinAfterDetach2() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        ((SalesOrder)object).getOrderDetails().clear();
      }

      if (object instanceof Product1)
      {
        ((Product1)object).getOrderDetails().clear();
      }
    }

    transaction.commit();

    for (Iterator<EObject> it = resource.getContents().iterator(); it.hasNext();)
    {
      EObject object = it.next();
      if (object instanceof SalesOrder)
      {
        it.remove();
      }

      if (object instanceof Customer)
      {
        ((Customer)object).getSalesOrders().clear();
      }
    }

    transaction.commit();

    CDOCommitInfo info = workspace.checkin();
    assertEquals(0, info.getNewObjects().size());
    assertEquals(1 + CUSTOMERS + PRODUCTS, info.getChangedObjects().size());
    assertEquals(ORDER_DETAILS + SALES_ORDERS, info.getDetachedObjects().size());

    CDOWorkspaceBase base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());
  }

  public void testCheckin2AfterModify() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED_" + product.getName());
      }
    }

    transaction.commit();

    CDOCommitInfo info = workspace.checkin();
    assertEquals(0, info.getNewObjects().size());
    assertEquals(PRODUCTS, info.getChangedObjects().size());
    assertEquals(0, info.getDetachedObjects().size());

    CDOWorkspaceBase base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());

    transaction = workspace.openTransaction();
    resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED2_" + product.getName());
      }
    }

    transaction.commit();

    info = workspace.checkin();
    assertEquals(0, info.getNewObjects().size());
    assertEquals(PRODUCTS, info.getChangedObjects().size());
    assertEquals(0, info.getDetachedObjects().size());

    base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testCheckin2AfterAdd() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    transaction.commit();

    CDOCommitInfo info = workspace.checkin();
    assertEquals(PRODUCTS, info.getNewObjects().size());
    assertEquals(1, info.getChangedObjects().size());
    assertEquals(0, info.getDetachedObjects().size());

    CDOWorkspaceBase base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());

    transaction = workspace.openTransaction();
    resource = transaction.getResource(getResourcePath(RESOURCE));
    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    transaction.commit();

    info = workspace.checkin();
    assertEquals(PRODUCTS, info.getNewObjects().size());
    assertEquals(1, info.getChangedObjects().size());
    assertEquals(0, info.getDetachedObjects().size());

    base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());
  }

  public void testCheckin2AfterDetach() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);

    CDOTransaction transaction = workspace.openTransaction();
    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        ((SalesOrder)object).getOrderDetails().clear();
      }

      if (object instanceof Product1)
      {
        ((Product1)object).getOrderDetails().clear();
      }
    }

    transaction.commit();

    CDOCommitInfo info = workspace.checkin();
    assertEquals(0, info.getNewObjects().size());
    assertEquals(SALES_ORDERS + PRODUCTS, info.getChangedObjects().size());
    assertEquals(ORDER_DETAILS, info.getDetachedObjects().size());

    CDOWorkspaceBase base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());

    transaction = workspace.openTransaction();
    resource = transaction.getResource(getResourcePath(RESOURCE));
    for (Iterator<EObject> it = resource.getContents().iterator(); it.hasNext();)
    {
      EObject object = it.next();
      if (object instanceof SalesOrder)
      {
        it.remove();
      }

      if (object instanceof Customer)
      {
        ((Customer)object).getSalesOrders().clear();
      }
    }

    transaction.commit();

    info = workspace.checkin();
    assertEquals(0, info.getNewObjects().size());
    assertEquals(1 + CUSTOMERS, info.getChangedObjects().size());
    assertEquals(SALES_ORDERS, info.getDetachedObjects().size());

    base = workspace.getBase();
    assertEquals(0, base.getIDs().size());
    assertEquals(info.getBranch().getPathName(), workspace.getBranchPath());
    assertEquals(info.getTimeStamp(), workspace.getTimeStamp());
  }

  public void testUpdateAfterMasterModify() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        product.setName("MODIFIED_" + product.getName());
      }
    }

    transaction.commit();

    CDOTransaction local = workspace.update(null);
    assertEquals(true, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(PRODUCTS, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());

    local.commit();
    assertEquals(false, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(0, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());
    assertEquals(0, workspace.getBase().getIDs().size());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects, dumpObjects(null, resource));
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testUpdateAfterMasterAdd() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    resource.getContents().add(createProduct(9999));
    transaction.commit();

    CDOTransaction local = workspace.update(null);
    assertEquals(true, local.isDirty());
    assertEquals(1, local.getNewObjects().size());
    assertEquals(1, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());

    local.commit();
    assertEquals(false, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(0, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());
    assertEquals(0, workspace.getBase().getIDs().size());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects + 1, dumpObjects(null, resource));
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testUpdateTwiceAfterMasterAdd() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    resource.getContents().add(createProduct(9999));
    transaction.commit();

    CDOTransaction local = workspace.update(null);
    assertEquals(true, local.isDirty());
    assertEquals(1, local.getNewObjects().size());
    assertEquals(1, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());

    local.commit();
    assertEquals(false, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(0, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());
    assertEquals(0, workspace.getBase().getIDs().size());
    local.close();

    local = workspace.update(null);
    assertEquals(false, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(0, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());
    assertEquals(0, workspace.getBase().getIDs().size());

    local.commit();
    assertEquals(false, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(0, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());
    assertEquals(0, workspace.getBase().getIDs().size());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects + 1, dumpObjects(null, resource));
  }

  public void testUpdateAfterMasterDetach() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    for (EObject object : resource.getContents())
    {
      if (object instanceof SalesOrder)
      {
        ((SalesOrder)object).getOrderDetails().clear();
      }

      if (object instanceof Product1)
      {
        ((Product1)object).getOrderDetails().clear();
      }
    }

    transaction.commit();

    CDOTransaction local = workspace.update(null);
    assertEquals(true, local.isDirty());
    assertEquals(SALES_ORDERS + PRODUCTS, local.getDirtyObjects().size());
    assertEquals(ORDER_DETAILS, local.getDetachedObjects().size());

    local.commit();
    assertEquals(false, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(0, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());
    assertEquals(0, workspace.getBase().getIDs().size());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects - ORDER_DETAILS, dumpObjects(null, resource));
  }

  public void testUpdateAfterMasterAndLocalModify() throws Exception
  {
    // Checkout local
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    // Modify master
    assertEquals(1, modifyProduct(transaction, 1, "MODIFIED_"));
    transaction.commit();

    // Modify local
    CDOTransaction local = workspace.openTransaction();
    assertEquals(1, modifyProduct(local, 2, "MODIFIED_"));
    local.commit();
    local.close();

    // Update local
    local = workspace.update(new DefaultCDOMerger.PerFeature.ManyValued());
    assertEquals(true, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(1, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());

    // Commit local
    local.commit();
    assertEquals(false, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(0, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());
    assertEquals(1, workspace.getBase().getIDs().size());

    // Verify local
    CDOView view = workspace.openView();
    assertEquals(2, countModifiedProduct(view));
  }

  @Requires(IRepositoryConfig.CAPABILITY_UUIDS)
  public void testUpdateAfterMasterAndLocalAdd() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    CDOResource resource = transaction.getResource(getResourcePath(RESOURCE));
    resource.getContents().add(createProduct(9999));
    transaction.commit();

    CDOTransaction local = workspace.openTransaction();
    resource = local.getResource(getResourcePath(RESOURCE));
    for (int i = 0; i < PRODUCTS; i++)
    {
      resource.getContents().add(createProduct(i));
    }

    local.commit();
    local.close();

    local = workspace.update(new DefaultCDOMerger.PerFeature.ManyValued());
    assertEquals(true, local.isDirty());
    assertEquals(1, local.getNewObjects().size());
    assertEquals(1, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());

    local.commit();
    assertEquals(false, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(0, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());
    assertEquals(6, workspace.getBase().getIDs().size());

    CDOView view = workspace.openView();
    resource = view.getResource(getResourcePath(RESOURCE));
    assertEquals(totalObjects + 1 + PRODUCTS, dumpObjects(null, resource));
  }

  public void testNoConflictMasterAndLocalModify() throws Exception
  {
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    assertEquals(1, modifyProduct(transaction, 1, "MODIFIED_"));
    transaction.commit();

    CDOTransaction local = workspace.openTransaction();
    assertEquals(1, modifyProduct(local, 1, "MODIFIED_"));
    local.commit();
    local.close();

    DefaultCDOMerger.PerFeature.ManyValued merger = new DefaultCDOMerger.PerFeature.ManyValued();
    local = workspace.update(merger);
    assertEquals(0, merger.getConflicts().size());
    assertEquals(false, local.isDirty());
    assertEquals(0, local.getNewObjects().size());
    assertEquals(0, local.getDirtyObjects().size());
    assertEquals(0, local.getDetachedObjects().size());

    CDOView view = workspace.openView();
    assertEquals(1, countModifiedProduct(view));
  }

  public void testConflictMasterAndLocalModify() throws Exception
  {
    CDOID id = CDOUtil.getCDOObject(products.get(1)).cdoID();

    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    assertEquals(1, modifyProduct(transaction, 1, "MODIFIED_1_"));
    transaction.commit();

    CDOTransaction local = workspace.openTransaction();
    assertEquals(1, modifyProduct(local, 1, "MODIFIED_2_"));
    local.commit();
    local.close();

    DefaultCDOMerger.PerFeature.ManyValued merger = new DefaultCDOMerger.PerFeature.ManyValued();

    try
    {
      local = workspace.update(merger);
      fail("ConflictException expected");
    }
    catch (ConflictException expected)
    {
      // SUCCESS
    }

    Map<CDOID, Conflict> conflicts = merger.getConflicts();
    assertEquals(1, conflicts.size());
    assertEquals(id, conflicts.values().iterator().next().getID());
    assertInactive(local);

    CDOView view = workspace.openView();
    assertEquals(1, countModifiedProduct(view));
  }

  public void testRevertNoTransaction() throws Exception
  {
    // Checkout local
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    // Modify local
    CDOTransaction local = workspace.openTransaction();
    assertEquals(1, modifyProduct(local, 2, "MODIFIED_"));

    local.commit();
    assertEquals(true, workspace.isDirty());

    local.close();
    assertEquals(true, workspace.isDirty());

    workspace.revert();
    assertEquals(false, workspace.isDirty());

    local = workspace.openTransaction();
    assertLocalEqualsMaster(local);
  }

  public void testRevertModify() throws Exception
  {
    // Checkout local
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    // Modify local
    CDOTransaction local = workspace.openTransaction();
    for (int i = 0; i < PRODUCTS; i++)
    {
      assertEquals(1, modifyProduct(local, i, "MODIFIED_"));

      local.commit();
      assertEquals(true, workspace.isDirty());
    }

    workspace.revert();
    assertEquals(false, workspace.isDirty());

    assertLocalEqualsMaster(local);
  }

  public void testRevertAdd() throws Exception
  {
    // Checkout local
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    // Add local
    CDOTransaction local = workspace.openTransaction();
    CDOResource resource = local.getResource(getResourcePath(RESOURCE));
    resource.getContents().add(createProduct(PRODUCTS));
    local.commit();
    assertEquals(true, workspace.isDirty());

    workspace.revert();
    assertEquals(false, workspace.isDirty());

    assertLocalEqualsMaster(local);
  }

  public void testRevertDetach() throws Exception
  {
    // Checkout local
    InternalCDOWorkspace workspace = checkout("MAIN", CDOBranchPoint.UNSPECIFIED_DATE);
    assertNotSame(CDOBranchPoint.UNSPECIFIED_DATE, workspace.getTimeStamp());

    // Detach local
    CDOTransaction local = workspace.openTransaction();
    CDOResource resource = local.getResource(getResourcePath(RESOURCE));
    resource.getContents().clear();
    local.commit();
    assertEquals(true, workspace.isDirty());

    workspace.revert();
    assertEquals(false, workspace.isDirty());

    assertLocalEqualsMaster(local);
  }

  protected IStore createLocalStore()
  {
    return getRepositoryConfig().createStore(CDOWorkspaceConfiguration.DEFAULT_LOCAL_REPOSITORY_NAME);
  }

  protected InternalCDOWorkspace checkout(String branchPath, long timeStamp)
  {
    disableConsole();
    CDOSessionConfigurationFactory remote = new RemoteSessionConfigurationFactory();

    File folder = createTempFolder("cdo-");
    CDOWorkspaceBase base = CDOWorkspaceUtil.createFolderWorkspaceBase(folder);
    IOUtil.ERR().println("CDOWorkspaceBaseline: " + folder.getAbsolutePath());

    CDOWorkspaceConfiguration config = CDOWorkspaceUtil.createWorkspaceConfiguration();
    config.setStore(localStore);
    config.setBase(base);
    config.setRemote(remote);
    config.setBranchPath(branchPath);
    config.setTimeStamp(timeStamp);
    config.setIDGenerationLocation(getRepository().getIDGenerationLocation());

    final InternalCDOWorkspace workspace = (InternalCDOWorkspace)config.checkout();
    workspaces.add(workspace);
    workspace.addListener(new LifecycleEventAdapter()
    {
      @Override
      protected void onDeactivated(ILifecycle lifecycle)
      {
        workspaces.remove(workspace);
      }
    });

    InternalRepository localRepository = workspace.getLocalRepository();
    registerRepository(localRepository);
    LifecycleUtil.activate(localRepository);

    return workspace;
  }

  private int dumpLocalStore(PrintStream out)
  {
    if (localStore instanceof CDOAllRevisionsProvider)
    {
      CDOAllRevisionsProvider provider = (CDOAllRevisionsProvider)localStore;
      Map<CDOBranch, List<CDORevision>> allRevisions = provider.getAllRevisions();
      int size = allRevisions.values().iterator().next().size();

      if (out != null)
      {
        CDORevisionUtil.dumpAllRevisions(allRevisions, out);
      }

      return size;
    }

    return 0;
  }

  private int dumpObjects(String prefix, EObject object)
  {
    if (prefix != null)
    {
      IOUtil.OUT().println(prefix + object);
    }

    int sum = 1;
    for (EObject content : object.eContents())
    {
      sum += dumpObjects(prefix != null ? prefix + "  " : null, content);
    }

    return sum;
  }

  private CDOResource createTestSet(CDOTransaction transaction) throws CommitException
  {
    disableConsole();
    CDOResource resource = transaction.createResource(getResourcePath(RESOURCE));
    fillResource(resource);

    totalObjects = 1;
    for (Iterator<EObject> it = resource.eAllContents(); it.hasNext();)
    {
      it.next();
      ++totalObjects;
    }

    transaction.commit();
    enableConsole();
    return resource;
  }

  private void fillResource(CDOResource resource)
  {
    for (int i = 0; i < PRODUCTS; i++)
    {
      Product1 product = createProduct(i);
      products.add(product);
      resource.getContents().add(product);
    }

    int id = 100;
    for (int i = 0; i < CUSTOMERS; i++)
    {
      Customer customer = createCustomer(i);
      customers.add(customer);
      resource.getContents().add(customer);

      for (int k = 0; k < SALES_ORDERS_PER_CUSTOMER; k++)
      {
        SalesOrder salesOrder = createSalesOrder(id++, customer);
        salesOrders.add(salesOrder);
        resource.getContents().add(salesOrder);

        for (Product1 product : products)
        {
          OrderDetail orderDetail = createOrderDetail(product, 55.123f);
          orderDetails.add(orderDetail);
          salesOrder.getOrderDetails().add(orderDetail);
        }
      }
    }
  }

  private Product1 createProduct(int index)
  {
    Product1 product = getModel1Factory().createProduct1();
    product.setName(getProductName(index));
    product.setVat(VAT.VAT15);
    return product;
  }

  private Customer createCustomer(int i)
  {
    Customer customer = getModel1Factory().createCustomer();
    customer.setCity("City " + i);
    customer.setName("" + i);
    customer.setStreet("Street " + i);
    return customer;
  }

  private SalesOrder createSalesOrder(int id, Customer customer)
  {
    SalesOrder salesOrder = getModel1Factory().createSalesOrder();
    salesOrder.setId(id);
    salesOrder.setCustomer(customer);
    return salesOrder;
  }

  private OrderDetail createOrderDetail(Product1 product, float price)
  {
    OrderDetail orderDetail = getModel1Factory().createOrderDetail();
    orderDetail.setPrice(price);
    orderDetail.setProduct(product);
    return orderDetail;
  }

  private String getProductName(int index)
  {
    return "Product No" + index;
  }

  private int modifyProduct(CDOTransaction transaction, int i, String prefix)
  {
    int count = 0;
    for (EObject object : transaction.getResource(getResourcePath(RESOURCE)).getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        String name = product.getName();
        if (getProductName(i).equals(name))
        {
          product.setName(prefix + name);
          ++count;
        }
      }
    }

    return count;
  }

  private int countModifiedProduct(CDOView view)
  {
    int count = 0;
    for (EObject object : view.getResource(getResourcePath(RESOURCE)).getContents())
    {
      if (object instanceof Product1)
      {
        Product1 product = (Product1)object;
        String name = product.getName();
        if (name.startsWith("MODIFIED"))
        {
          IOUtil.ERR().println(name);
          ++count;
        }
      }
    }

    return count;
  }

  private void assertLocalEqualsMaster(CDOTransaction local)
  {
    EList<EObject> masterContents = transaction.getResource(getResourcePath(RESOURCE)).getContents();
    EList<EObject> localContents = local.getResource(getResourcePath(RESOURCE)).getContents();
    assertEquals(masterContents.size(), localContents.size());

    for (int i = 0; i < masterContents.size(); i++)
    {
      EObject masterObject = masterContents.get(i);
      EObject localObject = localContents.get(i);
      assertEquals(true, EcoreUtil.equals(masterObject, localObject));

      CDORevision masterRevision = CDOUtil.getCDOObject(masterObject).cdoRevision();
      CDORevision localRevision = CDOUtil.getCDOObject(localObject).cdoRevision();
      assertEquals(masterRevision.getID(), localRevision.getID());
      assertEquals(masterRevision.getVersion(), localRevision.getVersion());
      assertEquals(masterRevision.getBranch().getID(), localRevision.getBranch().getID());
    }
  }

  /**
   * @author Eike Stepper
   */
  private final class RemoteSessionConfigurationFactory implements CDOSessionConfigurationFactory
  {
    public CDOSessionConfiguration createSessionConfiguration()
    {
      return new TestSessionConfiguration()
      {
        public CDOSession openSession()
        {
          return WorkspaceTest.this.openSession();
        }
      };
    }
  }
}
