public void testTemporaryObject() throws Exception {
    msg("Opening session");
    final CDOSession session = openSession();

    // ************************************************************* //

    msg("Creating category1");
    final Category category1A = getModel1Factory().createCategory();
    category1A.setName("category1");

    msg("Creating company");
    final Company companyA = getModel1Factory().createCompany();

    msg("Adding categories");
    companyA.getCategories().add(category1A);

    msg("Opening transaction");
    final CDOTransaction transaction = session.openTransaction();
    transaction.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);
    msg("Creating resource");
    final CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));

    msg("Adding company");
    resourceA.getContents().add(companyA);

    msg("Committing");

    final TestAdapter adapter = new TestAdapter();
    category1A.eAdapters().add(adapter);

    transaction.commit();

    // ************************************************************* //

    msg("Opening view");
    final CDOSession session2 = openSession();
    final CDOTransaction transaction2 = session2.openTransaction();
    transaction.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);

    final Category category1B =
        (Category)
            CDOUtil.getEObject(
                transaction2.getObject(CDOUtil.getCDOObject(category1A).cdoID(), true));

    msg("Changing name");
    category1B.setName("CHANGED NAME");

    assertEquals(0, adapter.getNotifications().length);

    msg("Committing");
    transaction2.commit();

    msg("Checking after commit");
    new PollingTimeOuter() {
      @Override
      protected boolean successful() {
        return adapter.getNotifications().length == 1;
      }
    }.assertNoTimeOut();
  }
  public void testSeparateSession() throws Exception {
    Category category1A = getModel1Factory().createCategory();
    category1A.setName("category1");

    Company companyA = getModel1Factory().createCompany();
    companyA.getCategories().add(category1A);

    CDOSession session = openSession();
    CDOTransaction transaction = session.openTransaction();
    transaction.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);

    CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
    resourceA.getContents().add(companyA);
    transaction.commit();

    final TestAdapter adapter = new TestAdapter();
    category1A.eAdapters().add(adapter);

    // ************************************************************* //

    CDOSession session2 = openSession();
    CDOTransaction transaction2 = session2.openTransaction();

    Category category1B =
        (Category)
            CDOUtil.getEObject(
                transaction2.getObject(CDOUtil.getCDOObject(category1A).cdoID(), true));
    category1B.setName("CHANGED NAME");
    assertEquals(0, adapter.getNotifications().length);

    transaction2.commit();

    new PollingTimeOuter() {
      @Override
      protected boolean successful() {
        // Change subscription leads to delta nnotification
        Notification[] notifications = adapter.getNotifications();
        return notifications.length == 1;
      }
    }.assertNoTimeOut();

    // Removing policy
    transaction.options().removeChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);
    adapter.clearNotifications();

    category1B.setName("CHANGED NAME_VERSION 2");
    assertEquals(0, adapter.getNotifications().length);

    transaction2.commit();

    new PollingTimeOuter() {
      @Override
      protected boolean successful() {
        // No change subscription, other session ==> no delta notification
        Notification[] notifications = adapter.getNotifications();
        return notifications.length != 0;
      }
    }.assertTimeOut();
  }
  @Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
  public void testTargetGoalDeltaVersion() throws Exception {
    skipStoreWithoutChangeSets();

    // setup 2 transactions.
    final CDOSession session1 = openSession();
    final CDOTransaction s1Tr1 = session1.openTransaction();
    s1Tr1.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);
    final CDOTransaction s1Tr2 = session1.openTransaction();
    s1Tr2.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);

    // create resource, container and 2 elements using transaction 1.
    final CDOResource resource = s1Tr1.createResource(getResourcePath("/test1"));
    RefMultiContained container = getModel4Factory().createRefMultiContained();
    resource.getContents().add(container);
    MultiContainedElement element1 = getModel4Factory().createMultiContainedElement();
    container.getElements().add(element1);
    MultiContainedElement element2 = getModel4Factory().createMultiContainedElement();
    container.getElements().add(element2);

    commitAndSync(s1Tr1, s1Tr2);

    // access container on transaction 2 to have it updated with a RevisionDelta.
    RefMultiContained container2 = s1Tr2.getObject(container);

    // setup another branch.
    final CDOBranch otherBranch = s1Tr1.getBranch().createBranch("other");
    final CDOTransaction s1Tr3 = session1.openTransaction(otherBranch);

    RefMultiContained otherContainer = s1Tr3.getObject(container);
    assertNotSame(null, otherContainer);
    assertEquals(true, otherContainer.getElements().size() > 0);

    // remove an element on the other branch.
    otherContainer.getElements().remove(0);

    commitAndSync(s1Tr3, s1Tr1);

    // merge the other branch to main (this creates the targetGoalDelta for the RevisionDelta).
    s1Tr1.merge(s1Tr3.getBranch().getHead(), new DefaultCDOMerger.PerFeature.ManyValued());

    commitAndSync(s1Tr1, s1Tr2);

    // check the change on tr2 and do another change.
    assertEquals(false, s1Tr1.isDirty());
    container2.getElements().remove(0);

    commitAndSync(s1Tr2, s1Tr1); // <--- this commit will throw the following exception:
    // java.util.ConcurrentModificationException:
    // Attempt by Transaction[2:2] to modify historical revision: RefMultiContained@OID4:0v1
    assertEquals(false, s1Tr1.isDirty());

    // check revision versions.
    assertEquals(
        CDOUtil.getCDOObject(container).cdoRevision().getVersion(),
        CDOUtil.getCDOObject(container2).cdoRevision().getVersion());
  }
  public void testSameSession_WithoutPolicy() throws Exception {
    final Category category1A = getModel1Factory().createCategory();
    category1A.setName("category1");

    final Company companyA = getModel1Factory().createCompany();
    companyA.getCategories().add(category1A);

    final CDOSession session = openSession();

    // ************************************************************* //

    final CDOTransaction transaction = session.openTransaction();

    final CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
    resourceA.getContents().add(companyA);

    transaction.commit();
    final TestAdapter adapter = new TestAdapter();
    category1A.eAdapters().add(adapter);

    // ************************************************************* //

    final CDOTransaction transaction2 = session.openTransaction();

    final Category category1B =
        (Category)
            CDOUtil.getEObject(
                transaction2.getObject(CDOUtil.getCDOObject(category1A).cdoID(), true));
    category1B.setName("CHANGED NAME");
    assertEquals(0, adapter.getNotifications().length);

    transaction2.commit();

    new PollingTimeOuter() {
      @Override
      protected boolean successful() {
        // Commit notifications from the same session always have full deltas
        Notification[] notifications = adapter.getNotifications();
        return notifications.length == 1;
      }
    }.assertNoTimeOut();

    // Adding policy
    transaction.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);
    adapter.clearNotifications();

    category1B.setName("CHANGED NAME_VERSION 2");
    assertEquals(0, adapter.getNotifications().length);

    transaction2.commit();

    new PollingTimeOuter() {
      @Override
      protected boolean successful() {
        // Commit notifications from the same session always have full deltas
        Notification[] notifications = adapter.getNotifications();
        return notifications.length == 1;
      }
    }.assertNoTimeOut();
  }
  @Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
  public void testXRefMergeManyValueTest() throws Exception {
    // setup transaction.
    final CDOSession session = openSession();
    final CDOTransaction tr1 = session.openTransaction();
    tr1.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);

    final CDOResource resource = tr1.createResource(getResourcePath("/test1"));
    RefMultiContained container = getModel4Factory().createRefMultiContained();
    resource.getContents().add(container);

    tr1.commit();
    sleep(1000);

    final CDOBranch otherBranch = tr1.getBranch().createBranch("other");
    final CDOTransaction tr2 = session.openTransaction(otherBranch);

    RefMultiContained otherContainer = tr2.getObject(container);
    assertNotNull(otherContainer);

    // add a new element on other branch at index 0.
    otherContainer.getElements().add(0, getModel4Factory().createMultiContainedElement());

    tr2.commit();

    // sleep to have the merger see the changes.
    sleep(1000);

    // merge the other branch to main.
    tr1.merge(tr2.getBranch().getHead(), new DefaultCDOMerger.PerFeature.ManyValued());

    tr1.commit();
    assertEquals(false, tr1.isDirty());
  }
  private void withAutoRelease(
      CDOSession session1, CDOView controlView, boolean mustReceiveNotifications)
      throws CommitException {
    TestListener2 controlViewListener = new TestListener2(CDOViewLocksChangedEvent.class);
    controlView.addListener(controlViewListener);

    CDOTransaction tx1 = session1.openTransaction();
    tx1.options().setAutoReleaseLocksEnabled(true);
    CDOResource res1 = tx1.getOrCreateResource(getResourcePath("r1"));
    res1.getContents().clear();
    Company company = getModel1Factory().createCompany();
    res1.getContents().add(company);
    tx1.commit();

    implicitRelease(company, LockType.WRITE, tx1, controlViewListener, mustReceiveNotifications);
    implicitRelease(company, LockType.READ, tx1, controlViewListener, mustReceiveNotifications);
    implicitRelease(company, LockType.OPTION, tx1, controlViewListener, mustReceiveNotifications);
  }
  public void testNotificationChain() throws Exception {
    msg("Opening session");
    final CDOSession session = openSession();

    // ************************************************************* //

    msg("Creating category1");
    final Category category1A = getModel1Factory().createCategory();
    category1A.setName("category1");

    msg("Creating company");
    final Company companyA = getModel1Factory().createCompany();

    msg("Adding categories");
    companyA.getCategories().add(category1A);

    msg("Opening transaction");
    final CDOTransaction transaction = session.openTransaction();

    transaction.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);

    msg("Creating resource");
    final CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));

    msg("Adding company");
    resourceA.getContents().add(companyA);

    msg("Committing");
    transaction.commit();

    final TestAdapter adapter = new TestAdapter();

    companyA.eAdapters().add(adapter);

    // ************************************************************* //

    msg("Opening view");
    final CDOSession session2 = openSession();
    final CDOTransaction transaction2 = session2.openTransaction();

    final Company company1B =
        (Company)
            CDOUtil.getEObject(
                transaction2.getObject(CDOUtil.getCDOObject(companyA).cdoID(), true));

    msg("Changing name");
    company1B.setName("TEST1");
    company1B.setCity("CITY1");

    final Category category2B = getModel1Factory().createCategory();
    company1B.getCategories().add(category2B);

    assertEquals(0, adapter.getNotifications().length);

    msg("Committing");
    transaction2.commit();

    msg("Checking after commit");
    new PollingTimeOuter() {
      @Override
      protected boolean successful() {
        return adapter.getNotifications().length == 3;
      }
    }.assertNoTimeOut();

    int count = 0;
    for (Notification notification : adapter.getNotifications()) {
      CDODeltaNotification cdoNotification = (CDODeltaNotification) notification;
      if (adapter.getNotifications().length - 1 == count) {
        assertEquals(false, cdoNotification.hasNext());
      } else {
        assertEquals(true, cdoNotification.hasNext());
      }

      if (notification.getFeature() == getModel1Package().getCategory_Name()) {
        assertEquals(Notification.SET, notification.getEventType());
        assertEquals("TEST1", notification.getNewStringValue());
      } else if (notification.getFeature() == getModel1Package().getAddress_City()) {
        assertEquals(Notification.SET, notification.getEventType());
        assertEquals("CITY1", notification.getNewStringValue());
      } else if (notification.getFeature() == getModel1Package().getCompany_Categories()) {
        assertEquals(Notification.ADD, notification.getEventType());
        assertEquals(1, notification.getPosition());
        assertEquals(
            transaction.getObject(CDOUtil.getCDOObject(category2B).cdoID(), true),
            notification.getNewValue());
      } else {
        assertEquals(false, false);
      }

      count++;
    }
  }