Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.common/src/org')
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranch.java1
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchManager.java55
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchTag.java70
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java18
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchManagerImpl.java637
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchTagImpl.java313
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranchManager.java89
7 files changed, 1178 insertions, 5 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranch.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranch.java
index 0a197fd1d9..e8b7116775 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranch.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranch.java
@@ -197,4 +197,5 @@ public interface CDOBranch extends CDOBranchPoint, CDONameProvider, IContainer<C
*/
@Deprecated
public void rename(String newName);
+
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchManager.java
index 407df9aa8b..3294322c15 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchManager.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchManager.java
@@ -12,6 +12,8 @@ package org.eclipse.emf.cdo.common.branch;
import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.net4j.util.container.IContainer;
+import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.INotifier;
/**
@@ -82,4 +84,57 @@ public interface CDOBranchManager extends INotifier
* This is a blocking call.
*/
public int getBranches(int startID, int endID, CDOBranchHandler handler);
+
+ /**
+ * @since 4.11
+ */
+ public CDOBranchTag createTag(String name, CDOBranchPoint branchPoint);
+
+ /**
+ * @since 4.11
+ */
+ public CDOBranchTag getTag(String name);
+
+ /**
+ * @since 4.11
+ */
+ public CDOTagList getTagList();
+
+ /**
+ * @author Eike Stepper
+ * @since 4.11
+ */
+ public interface CDOTagList extends IContainer<CDOBranchTag>
+ {
+ /**
+ * Returns the {@link CDOBranchManager branch manager} that manages this {@link CDOTagList tag list}, never <code>null</code>.
+ */
+ public CDOBranchManager getBranchManager();
+
+ public CDOBranchTag[] getTags();
+
+ public CDOBranchTag[] getTags(CDOBranch branch);
+
+ /**
+ * @author Eike Stepper
+ */
+ public interface TagListEvent extends IEvent
+ {
+ public CDOTagList getTagList();
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public interface TagRenamedEvent extends TagListEvent, CDOBranchTag.TagRenamedEvent
+ {
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public interface TagMovedEvent extends TagListEvent, CDOBranchTag.TagRenamedEvent
+ {
+ }
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchTag.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchTag.java
index 1c89ae5f57..1e5601c518 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchTag.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchTag.java
@@ -12,6 +12,8 @@ package org.eclipse.emf.cdo.common.branch;
import org.eclipse.emf.cdo.common.util.CDONameProvider;
+import org.eclipse.net4j.util.event.IEvent;
+
/**
* A persistent, named {@link CDOBranchPoint branch point}.
*
@@ -20,11 +22,77 @@ import org.eclipse.emf.cdo.common.util.CDONameProvider;
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
-public interface CDOBranchTag extends CDOBranchPoint, CDONameProvider
+public interface CDOBranchTag extends CDOBranchPoint, CDONameProvider, Comparable<CDOBranchTag>
{
/**
+ * Returns the branch manager that manages this branch, never <code>null</code>.
+ *
+ * @since 4.11
+ */
+ public CDOBranchManager getBranchManager();
+
+ /**
* Returns the name of this branch tag.
*/
@Override
public String getName();
+
+ /**
+ * @since 4.11
+ */
+ public void setName(String name);
+
+ /**
+ * @since 4.11
+ */
+ public void move(CDOBranchPoint branchPoint);
+
+ /**
+ * @since 4.11
+ */
+ public void delete();
+
+ /**
+ * @since 4.11
+ */
+ public boolean isDeleted();
+
+ /**
+ * @author Eike Stepper
+ * @since 4.11
+ */
+ public interface TagEvent extends IEvent
+ {
+ public CDOBranchTag getTag();
+ }
+
+ /**
+ * @author Eike Stepper
+ * @since 4.11
+ */
+ public interface TagRenamedEvent extends TagEvent
+ {
+ public String getOldName();
+
+ public String getNewName();
+ }
+
+ /**
+ * @author Eike Stepper
+ * @since 4.11
+ */
+ public interface TagMovedEvent extends TagEvent
+ {
+ public CDOBranchPoint getOldBranchPoint();
+
+ public CDOBranchPoint getNewBranchPoint();
+ }
+
+ /**
+ * @author Eike Stepper
+ * @since 4.11
+ */
+ public interface TagDeletedEvent extends TagEvent
+ {
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
index 73b012542a..f186a6c203 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
@@ -32,8 +32,9 @@ public interface CDOProtocolConstants
* @since 4.2
* @noreference This field is not intended to be referenced by clients.
*/
- public static final int PROTOCOL_VERSION = 37; // SIGNAL_ACKNOWLEDGE_COMPRESSED_STRINGS
+ public static final int PROTOCOL_VERSION = 38; // CDOBranchTag support
+ // public static final int PROTOCOL_VERSION = 37; // SIGNAL_ACKNOWLEDGE_COMPRESSED_STRINGS
// public static final int PROTOCOL_VERSION = 36; // CDOID.NIL
// public static final int PROTOCOL_VERSION = 35; // DiffieHellman.Server.Challenge.getSecretAlgorithmKeyLen()
// public static final int PROTOCOL_VERSION = 34; // CDOSessionProtocol.loadMergeData2()
@@ -333,6 +334,21 @@ public interface CDOProtocolConstants
*/
public static final short SIGNAL_UNIT = 62;
+ /**
+ * @since 4.11
+ */
+ public static final short SIGNAL_LOAD_TAGS = 63;
+
+ /**
+ * @since 4.11
+ */
+ public static final short SIGNAL_CHANGE_TAG = 64;
+
+ /**
+ * @since 4.11
+ */
+ public static final short SIGNAL_TAG_NOTIFICATION = 65;
+
// //////////////////////////////////////////////////////////////////////
// Session Refresh
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchManagerImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchManagerImpl.java
index b8fdd9b616..8ba1a47c7b 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchManagerImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchManagerImpl.java
@@ -16,8 +16,15 @@ import org.eclipse.emf.cdo.common.branch.CDOBranchChangedEvent;
import org.eclipse.emf.cdo.common.branch.CDOBranchChangedEvent.ChangeKind;
import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
+import org.eclipse.emf.cdo.common.branch.CDOBranchManager.CDOTagList.TagListEvent;
+import org.eclipse.emf.cdo.common.branch.CDOBranchManager.CDOTagList.TagRenamedEvent;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchTag;
+import org.eclipse.emf.cdo.common.branch.CDOBranchTag.TagEvent;
+import org.eclipse.emf.cdo.common.branch.CDOBranchTag.TagMovedEvent;
+import org.eclipse.emf.cdo.common.util.CDOException;
import org.eclipse.emf.cdo.common.util.CDOTimeProvider;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader.BranchInfo;
@@ -26,10 +33,17 @@ import org.eclipse.net4j.util.collection.Pair;
import org.eclipse.net4j.util.container.Container;
import org.eclipse.net4j.util.event.Event;
import org.eclipse.net4j.util.ref.ReferenceValueMap;
-import org.eclipse.net4j.util.ref.ReferenceValueMap.Soft;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
/**
* @author Eike Stepper
@@ -42,7 +56,15 @@ public class CDOBranchManagerImpl extends Container<CDOBranch> implements Intern
private InternalCDOBranch mainBranch;
- private Map<Integer, InternalCDOBranch> branches = createMap();
+ private Map<Integer, InternalCDOBranch> branches = createBranchMap();
+
+ private Map<String, CDOBranchTagImpl> tags = createTagMap();
+
+ private Reference<CDOTagListImpl> tagListReference;
+
+ private List<TagChange> tagChangeQueue = new ArrayList<>();
+
+ private int tagModCount = -1;
public CDOBranchManagerImpl()
{
@@ -272,6 +294,328 @@ public class CDOBranchManagerImpl extends Container<CDOBranch> implements Intern
}
@Override
+ public int getTagModCount()
+ {
+ return tagModCount;
+ }
+
+ @Override
+ public void setTagModCount(int tagModCount)
+ {
+ synchronized (tags)
+ {
+ boolean initial = this.tagModCount == -1;
+ this.tagModCount = tagModCount;
+
+ if (initial)
+ {
+ executeTagChanges();
+ }
+ }
+ }
+
+ @Override
+ public void handleTagChanged(int modCount, String oldName, String newName, CDOBranchPoint branchPoint)
+ {
+ synchronized (tags)
+ {
+ tagChangeQueue.add(new TagChange(modCount, oldName, newName, branchPoint));
+ tagChangeQueue.sort(null);
+ executeTagChanges();
+ }
+ }
+
+ protected void executeTagChanges()
+ {
+ while (!tagChangeQueue.isEmpty() && tagModCount != -1)
+ {
+ TagChange tagChange = tagChangeQueue.get(0);
+ int newModCount = tagModCount + 1;
+
+ if (tagChange.getModCount() == newModCount)
+ {
+ tagModCount = newModCount;
+ executeTagChange(tagChange.getOldName(), tagChange.getNewName(), tagChange.getBranchPoint());
+ tagChangeQueue.remove(0);
+ }
+ }
+ }
+
+ protected void executeTagChange(String oldName, String newName, CDOBranchPoint branchPoint)
+ {
+ switch (InternalCDOBranchManager.getTagChangeKind(oldName, newName, branchPoint))
+ {
+ case CREATED:
+ createTagInternal(newName, branchPoint);
+ break;
+
+ case RENAMED:
+ renameTagInternal(oldName, newName);
+ break;
+
+ case MOVED:
+ moveTagInternal(oldName, branchPoint);
+ break;
+
+ case DELETED:
+ deleteTagInternal(oldName);
+ break;
+ }
+ }
+
+ @Override
+ public CDOBranchPoint changeTagWithModCount(AtomicInteger modCount, String oldName, String newName, CDOBranchPoint branchPoint)
+ {
+ synchronized (tags)
+ {
+ if (modCount != null)
+ {
+ if (modCount.get() != tagModCount)
+ {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ CDOBranchPoint result = null;
+
+ switch (InternalCDOBranchManager.getTagChangeKind(oldName, newName, branchPoint))
+ {
+ case CREATED:
+ {
+ CDOBranchTagImpl tag = tags.get(newName);
+ if (tag != null)
+ {
+ throw new CDOException("Tag name exists: " + newName);
+ }
+
+ boolean success = false;
+ if (branchLoader instanceof BranchLoader4)
+ {
+ result = ((BranchLoader4)branchLoader).changeTag(modCount, null, newName, branchPoint);
+ if (result != null)
+ {
+ branchPoint = result;
+ result = null;
+ }
+
+ success = true;
+ }
+
+ if (success)
+ {
+ result = createTagInternal(newName, branchPoint);
+ }
+
+ break;
+ }
+
+ case RENAMED:
+ {
+ ((BranchLoader4)branchLoader).changeTag(modCount, oldName, newName, null);
+ renameTagInternal(oldName, newName);
+ break;
+ }
+
+ case MOVED:
+ {
+ result = ((BranchLoader4)branchLoader).changeTag(modCount, oldName, null, branchPoint);
+ if (result != null)
+ {
+ branchPoint = result;
+ result = null;
+ }
+
+ moveTagInternal(oldName, branchPoint);
+ break;
+ }
+
+ case DELETED:
+ {
+ ((BranchLoader4)branchLoader).changeTag(modCount, oldName, null, null);
+ deleteTagInternal(oldName);
+ break;
+ }
+ }
+
+ ++tagModCount;
+ if (modCount != null)
+ {
+ modCount.set(tagModCount);
+ }
+
+ return result;
+ }
+ }
+
+ @Override
+ public CDOBranchTag createTag(String name, CDOBranchPoint branchPoint)
+ {
+ synchronized (tags)
+ {
+ AtomicInteger modCount = new AtomicInteger(tagModCount);
+ return (CDOBranchTag)changeTagWithModCount(modCount, null, name, branchPoint);
+ }
+ }
+
+ @Override
+ public void renameTag(String oldName, String newName)
+ {
+ synchronized (tags)
+ {
+ AtomicInteger modCount = new AtomicInteger(tagModCount);
+ changeTagWithModCount(modCount, oldName, newName, null);
+ }
+ }
+
+ @Override
+ public void moveTag(CDOBranchTag tag, CDOBranchPoint branchPoint)
+ {
+ synchronized (tags)
+ {
+ String name = tag.getName();
+
+ AtomicInteger modCount = new AtomicInteger(tagModCount);
+ changeTagWithModCount(modCount, name, null, branchPoint);
+ }
+ }
+
+ @Override
+ public void deleteTag(CDOBranchTag tag)
+ {
+ synchronized (tags)
+ {
+ String name = tag.getName();
+
+ AtomicInteger modCount = new AtomicInteger(tagModCount);
+ changeTagWithModCount(modCount, name, null, null);
+ }
+ }
+
+ private CDOBranchTagImpl createTagInternal(String name, CDOBranchPoint branchPoint)
+ {
+ CDOBranchTagImpl tag = new CDOBranchTagImpl(name, branchPoint.getBranch(), branchPoint.getTimeStamp());
+ tags.put(name, tag);
+
+ CDOTagListImpl tagList = getTagListOrNull();
+ if (tagList != null)
+ {
+ tagList.addTag(tag);
+ }
+
+ return tag;
+ }
+
+ private void renameTagInternal(String oldName, String newName)
+ {
+ CDOBranchTagImpl tag = tags.remove(oldName);
+ tag.setNameInternal(newName);
+ tags.put(newName, tag);
+
+ CDOTagListImpl tagList = getTagListOrNull();
+ if (tagList != null)
+ {
+ tagList.fireTagRenamedEvent(tag, oldName, newName);
+ }
+
+ tag.fireTagRenamedEvent(oldName, newName);
+ }
+
+ private void moveTagInternal(String name, CDOBranchPoint branchPoint)
+ {
+ CDOBranchTagImpl tag = tags.get(name);
+ CDOBranchPoint oldBranchPoint = CDOBranchUtil.copyBranchPoint(tag);
+ tag.moveInternal(branchPoint.getBranch(), branchPoint.getTimeStamp());
+
+ CDOTagListImpl tagList = getTagListOrNull();
+ if (tagList != null)
+ {
+ tagList.fireTagMovedEvent(tag, oldBranchPoint, branchPoint);
+ }
+
+ tag.fireTagMovedEvent(oldBranchPoint, branchPoint);
+ }
+
+ private void deleteTagInternal(String name)
+ {
+ CDOBranchTagImpl tag = tags.remove(name);
+ tag.deleteInternal();
+
+ CDOTagListImpl tagList = getTagListOrNull();
+ if (tagList != null)
+ {
+ tagList.removeTag(tag);
+ }
+
+ tag.fireTagDeletedEvent();
+ }
+
+ @Override
+ public CDOBranchTag getTag(String name)
+ {
+ synchronized (tags)
+ {
+ CDOBranchTagImpl tag = tags.get(name);
+ if (tag == null && branchLoader instanceof BranchLoader4)
+ {
+ AtomicReference<BranchInfo> result = new AtomicReference<>();
+ ((BranchLoader4)branchLoader).loadTags(name, branchInfo -> result.set(branchInfo));
+
+ BranchInfo branchInfo = result.get();
+ if (branchInfo != null)
+ {
+ int branchID = branchInfo.getBaseBranchID();
+ long timeStamp = branchInfo.getBaseTimeStamp();
+
+ InternalCDOBranch branch = getBranch(branchID);
+ tag = new CDOBranchTagImpl(name, branch, timeStamp);
+ tags.put(name, tag);
+ }
+ }
+
+ return tag;
+ }
+ }
+
+ @Override
+ public CDOTagList getTagList()
+ {
+ synchronized (tags)
+ {
+ CDOTagListImpl tagList = getTagListOrNull();
+ if (tagList != null)
+ {
+ return tagList;
+ }
+
+ if (branchLoader instanceof BranchLoader4)
+ {
+ CDOTagListImpl newTagList = new CDOTagListImpl();
+ ((BranchLoader4)branchLoader).loadTags(null, branchInfo -> newTagList.addTag(branchInfo));
+ tagListReference = createTagListReference(newTagList);
+
+ newTagList.activate();
+ return newTagList;
+ }
+
+ return null;
+ }
+ }
+
+ private CDOTagListImpl getTagListOrNull()
+ {
+ if (tagListReference != null)
+ {
+ CDOTagListImpl tagList = tagListReference.get();
+ if (tagList != null)
+ {
+ return tagList;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
public String toString()
{
return MessageFormat.format("BranchManager[loader={0}]", branchLoader);
@@ -292,11 +636,21 @@ public class CDOBranchManagerImpl extends Container<CDOBranch> implements Intern
return true;
}
- protected Soft<Integer, InternalCDOBranch> createMap()
+ protected Map<Integer, InternalCDOBranch> createBranchMap()
+ {
+ return new ReferenceValueMap.Soft<>();
+ }
+
+ protected Map<String, CDOBranchTagImpl> createTagMap()
{
return new ReferenceValueMap.Soft<>();
}
+ protected Reference<CDOTagListImpl> createTagListReference(CDOTagListImpl tagList)
+ {
+ return new SoftReference<>(tagList);
+ }
+
@Override
protected void doBeforeActivate() throws Exception
{
@@ -308,6 +662,283 @@ public class CDOBranchManagerImpl extends Container<CDOBranch> implements Intern
/**
* @author Eike Stepper
*/
+ public final class CDOTagListImpl extends Container<CDOBranchTag> implements CDOTagList
+ {
+ private final List<CDOBranchTag> list = new ArrayList<>();
+
+ private CDOBranchTag[] array;
+
+ public CDOTagListImpl()
+ {
+ }
+
+ @Override
+ public CDOBranchManager getBranchManager()
+ {
+ return CDOBranchManagerImpl.this;
+ }
+
+ @Override
+ public CDOBranchTag[] getElements()
+ {
+ return getTags();
+ }
+
+ @Override
+ public CDOBranchTag[] getTags()
+ {
+ synchronized (list)
+ {
+ if (array == null)
+ {
+ array = list.toArray(new CDOBranchTag[list.size()]);
+ Arrays.sort(array);
+ }
+
+ return array;
+ }
+ }
+
+ @Override
+ public CDOBranchTag[] getTags(CDOBranch branch)
+ {
+ List<CDOBranchTag> result = new ArrayList<>();
+
+ synchronized (list)
+ {
+ for (CDOBranchTag tag : list)
+ {
+ if (tag.getBranch() == branch)
+ {
+ result.add(tag);
+ }
+ }
+ }
+
+ return result.toArray(new CDOBranchTag[result.size()]);
+ }
+
+ private void addTag(BranchInfo branchInfo)
+ {
+ String name = branchInfo.getName();
+ CDOBranchTagImpl tag = tags.get(name);
+ if (tag == null)
+ {
+ int branchID = branchInfo.getBaseBranchID();
+ long timeStamp = branchInfo.getBaseTimeStamp();
+
+ InternalCDOBranch branch = getBranch(branchID);
+ tag = new CDOBranchTagImpl(name, branch, timeStamp);
+ tags.put(name, tag);
+ }
+
+ addTag(tag);
+ }
+
+ private void addTag(CDOBranchTag tag)
+ {
+ synchronized (list)
+ {
+ list.add(tag);
+ array = null;
+ }
+
+ if (isActive())
+ {
+ fireElementAddedEvent(tag);
+ }
+ }
+
+ private void removeTag(CDOBranchTag tag)
+ {
+ synchronized (list)
+ {
+ if (list.remove(tag))
+ {
+ array = null;
+ }
+ else
+ {
+ tag = null;
+ }
+ }
+
+ if (tag != null)
+ {
+ fireElementRemovedEvent(tag);
+ }
+ }
+
+ private void fireTagRenamedEvent(CDOBranchTagImpl tag, String oldName, String newName)
+ {
+ fireEvent(new TagRenamedEventImpl(this, tag, oldName, newName));
+ }
+
+ private void fireTagMovedEvent(CDOBranchTagImpl tag, CDOBranchPoint oldBranchPoint, CDOBranchPoint newBranchPoint)
+ {
+ fireEvent(new TagMovedEventImpl(this, tag, oldBranchPoint, newBranchPoint));
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static abstract class TagListEventImpl extends Event implements TagListEvent, TagEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ private final CDOBranchTagImpl tag;
+
+ public TagListEventImpl(CDOTagListImpl tagList, CDOBranchTagImpl tag)
+ {
+ super(tagList);
+ this.tag = tag;
+ }
+
+ @Override
+ public CDOTagList getTagList()
+ {
+ return (CDOTagList)getSource();
+ }
+
+ @Override
+ public CDOBranchTagImpl getTag()
+ {
+ return tag;
+ }
+
+ @Override
+ protected String formatAdditionalParameters()
+ {
+ return "tag=" + tag;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class TagRenamedEventImpl extends TagListEventImpl implements TagRenamedEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ private final String oldName;
+
+ private final String newName;
+
+ public TagRenamedEventImpl(CDOTagListImpl tagList, CDOBranchTagImpl tag, String oldName, String newName)
+ {
+ super(tagList, tag);
+ this.oldName = oldName;
+ this.newName = newName;
+ }
+
+ @Override
+ public String getOldName()
+ {
+ return oldName;
+ }
+
+ @Override
+ public String getNewName()
+ {
+ return newName;
+ }
+
+ @Override
+ protected String formatAdditionalParameters()
+ {
+ return super.formatAdditionalParameters() + ", oldName=" + oldName + ", newName=" + newName;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class TagMovedEventImpl extends TagListEventImpl implements TagMovedEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ private final CDOBranchPoint oldBranchPoint;
+
+ private final CDOBranchPoint newBranchPoint;
+
+ public TagMovedEventImpl(CDOTagListImpl tagList, CDOBranchTagImpl tag, CDOBranchPoint oldBranchPoint, CDOBranchPoint newBranchPoint)
+ {
+ super(tagList, tag);
+ this.oldBranchPoint = oldBranchPoint;
+ this.newBranchPoint = newBranchPoint;
+ }
+
+ @Override
+ public CDOBranchPoint getOldBranchPoint()
+ {
+ return oldBranchPoint;
+ }
+
+ @Override
+ public CDOBranchPoint getNewBranchPoint()
+ {
+ return newBranchPoint;
+ }
+
+ @Override
+ protected String formatAdditionalParameters()
+ {
+ return super.formatAdditionalParameters() + ", oldBranchPoint=" + oldBranchPoint + ", newBranchPoint=" + newBranchPoint;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class TagChange implements Comparable<TagChange>
+ {
+ private final int modCount;
+
+ private final String oldName;
+
+ private final String newName;
+
+ private final CDOBranchPoint branchPoint;
+
+ public TagChange(int modCount, String oldName, String newName, CDOBranchPoint branchPoint)
+ {
+ this.modCount = modCount;
+ this.oldName = oldName;
+ this.newName = newName;
+ this.branchPoint = branchPoint;
+ }
+
+ public int getModCount()
+ {
+ return modCount;
+ }
+
+ public String getOldName()
+ {
+ return oldName;
+ }
+
+ public String getNewName()
+ {
+ return newName;
+ }
+
+ public CDOBranchPoint getBranchPoint()
+ {
+ return branchPoint;
+ }
+
+ @Override
+ public int compareTo(TagChange o)
+ {
+ return Integer.compare(modCount, o.modCount);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
private static class BranchChangedEvent extends Event implements CDOBranchChangedEvent
{
private static final long serialVersionUID = 1L;
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchTagImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchTagImpl.java
new file mode 100644
index 0000000000..24eb11658c
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchTagImpl.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2020 Eike Stepper (Loehne, 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.internal.common.branch;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchTag;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+
+import org.eclipse.net4j.util.CheckUtil;
+import org.eclipse.net4j.util.event.Event;
+import org.eclipse.net4j.util.event.Notifier;
+
+import java.text.MessageFormat;
+
+/**
+ * @author Eike Stepper
+ * @since 4.11
+ */
+public class CDOBranchTagImpl extends Notifier implements CDOBranchTag
+{
+ private String name;
+
+ private InternalCDOBranch branch;
+
+ private long timeStamp;
+
+ public CDOBranchTagImpl(String name, CDOBranch branch, long timeStamp)
+ {
+ checkName(name);
+ checkBranchPoint(branch, timeStamp);
+
+ this.name = name;
+ this.branch = (InternalCDOBranch)branch;
+ this.timeStamp = timeStamp;
+ }
+
+ @Override
+ public CDOBranch getBranch()
+ {
+ return branch;
+ }
+
+ @Override
+ public long getTimeStamp()
+ {
+ return timeStamp;
+ }
+
+ @Override
+ public InternalCDOBranchManager getBranchManager()
+ {
+ if (branch != null)
+ {
+ return branch.getBranchManager();
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public void setName(String name)
+ {
+ checkName(name);
+
+ if (name.equals(this.name))
+ {
+ return;
+ }
+
+ InternalCDOBranchManager branchManager = getBranchManager();
+ branchManager.renameTag(this.name, name);
+ }
+
+ void setNameInternal(String name)
+ {
+ this.name = name;
+ }
+
+ void fireTagRenamedEvent(String oldName, String newName)
+ {
+ fireEvent(new TagRenamedEventImpl(this, oldName, newName));
+ }
+
+ @Override
+ public void move(CDOBranchPoint branchPoint)
+ {
+ CDOBranch newBranch = branchPoint.getBranch();
+ long newTimeStamp = branchPoint.getTimeStamp();
+ checkBranchPoint(newBranch, newTimeStamp);
+
+ branchPoint = CDOBranchUtil.adjustBranchPoint(branchPoint, getBranchManager());
+ if (branchPoint.equals(CDOBranchUtil.copyBranchPoint(this)))
+ {
+ return;
+ }
+
+ InternalCDOBranchManager branchManager = getBranchManager();
+ branchManager.moveTag(this, branchPoint);
+
+ moveInternal(newBranch, newTimeStamp);
+ }
+
+ void moveInternal(CDOBranch branch, long timeStamp)
+ {
+ this.branch = (InternalCDOBranch)branch;
+ this.timeStamp = timeStamp;
+ }
+
+ void fireTagMovedEvent(CDOBranchPoint oldBranchPoint, CDOBranchPoint newBranchPoint)
+ {
+ fireEvent(new TagMovedEventImpl(this, oldBranchPoint, newBranchPoint));
+ }
+
+ @Override
+ public void delete()
+ {
+ if (!isDeleted())
+ {
+ InternalCDOBranchManager branchManager = getBranchManager();
+ branchManager.deleteTag(this);
+
+ deleteInternal();
+ }
+ }
+
+ void deleteInternal()
+ {
+ branch = null;
+ timeStamp = CDOBranchPoint.UNSPECIFIED_DATE;
+ }
+
+ void fireTagDeletedEvent()
+ {
+ fireEvent(new TagDeletedEventImpl(this));
+ }
+
+ @Override
+ public boolean isDeleted()
+ {
+ return branch == null;
+ }
+
+ /*
+ * The hashCode() method is only overridden to make the compiler happy.
+ */
+ @Override
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ return this == obj;
+ }
+
+ @Override
+ public int compareTo(CDOBranchTag o)
+ {
+ long ts1 = timeStamp;
+ long ts2 = o.getTimeStamp();
+ if (ts1 == ts2)
+ {
+ int b1 = branch.getID();
+ int b2 = o.getBranch().getID();
+ return Integer.compare(b1, b2);
+ }
+
+ return Long.compare(ts1, ts2);
+ }
+
+ @Override
+ public String toString()
+ {
+ return MessageFormat.format("BranchTag[{0}, {1}, {2}]", name, branch, CDOCommonUtil.formatTimeStamp(timeStamp)); //$NON-NLS-1$
+ }
+
+ private static void checkName(String name)
+ {
+ CheckUtil.checkArg(name != null && !name.isEmpty(), "Invalid name");
+ }
+
+ private static void checkBranchPoint(CDOBranch branch, long timeStamp)
+ {
+ CheckUtil.checkArg(branch, "branch");
+ CheckUtil.checkArg(timeStamp > CDOBranchPoint.UNSPECIFIED_DATE, "Invalid timeStamp");
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static abstract class TagEventImpl extends Event implements TagEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ public TagEventImpl(CDOBranchTagImpl tag)
+ {
+ super(tag);
+ }
+
+ @Override
+ public CDOBranchTag getTag()
+ {
+ return (CDOBranchTag)getSource();
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class TagRenamedEventImpl extends TagEventImpl implements TagRenamedEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ private final String oldName;
+
+ private final String newName;
+
+ public TagRenamedEventImpl(CDOBranchTagImpl tag, String oldName, String newName)
+ {
+ super(tag);
+ this.oldName = oldName;
+ this.newName = newName;
+ }
+
+ @Override
+ public String getOldName()
+ {
+ return oldName;
+ }
+
+ @Override
+ public String getNewName()
+ {
+ return newName;
+ }
+
+ @Override
+ protected String formatAdditionalParameters()
+ {
+ return "oldName=" + oldName + ", newName=" + newName;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class TagMovedEventImpl extends TagEventImpl implements TagMovedEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ private final CDOBranchPoint oldBranchPoint;
+
+ private final CDOBranchPoint newBranchPoint;
+
+ public TagMovedEventImpl(CDOBranchTagImpl tag, CDOBranchPoint oldBranchPoint, CDOBranchPoint newBranchPoint)
+ {
+ super(tag);
+ this.oldBranchPoint = oldBranchPoint;
+ this.newBranchPoint = newBranchPoint;
+ }
+
+ @Override
+ public CDOBranchPoint getOldBranchPoint()
+ {
+ return oldBranchPoint;
+ }
+
+ @Override
+ public CDOBranchPoint getNewBranchPoint()
+ {
+ return newBranchPoint;
+ }
+
+ @Override
+ protected String formatAdditionalParameters()
+ {
+ return "oldBranchPoint=" + oldBranchPoint + ", newBranchPoint=" + newBranchPoint;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class TagDeletedEventImpl extends TagEventImpl implements TagDeletedEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ public TagDeletedEventImpl(CDOBranchTagImpl tag)
+ {
+ super(tag);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranchManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranchManager.java
index 4d1ba43654..9311e9a17b 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranchManager.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranchManager.java
@@ -15,6 +15,8 @@ import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchChangedEvent.ChangeKind;
import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchTag;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.util.CDOTimeProvider;
@@ -24,6 +26,8 @@ import org.eclipse.net4j.util.collection.Pair;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
/**
* If the meaning of this type isn't clear, there really should be more of a description here...
@@ -91,6 +95,73 @@ public interface InternalCDOBranchManager extends CDOBranchManager, ILifecycle
public void handleBranchChanged(InternalCDOBranch branch, ChangeKind changeKind);
/**
+ * @since 4.11
+ */
+ public int getTagModCount();
+
+ /**
+ * @since 4.11
+ */
+ public void setTagModCount(int tagModCount);
+
+ /**
+ * @since 4.11
+ */
+ public void renameTag(String oldName, String newName);
+
+ /**
+ * @since 4.11
+ */
+ public void moveTag(CDOBranchTag tag, CDOBranchPoint branchPoint);
+
+ /**
+ * @since 4.11
+ */
+ public void deleteTag(CDOBranchTag tag);
+
+ /**
+ * @since 4.11
+ */
+ public CDOBranchPoint changeTagWithModCount(AtomicInteger modCount, String oldName, String newName, CDOBranchPoint branchPoint);
+
+ /**
+ * @since 4.11
+ */
+ public void handleTagChanged(int modCount, String oldName, String newName, CDOBranchPoint branchPoint);
+
+ /**
+ * @since 4.11
+ */
+ public static TagChangeKind getTagChangeKind(String oldName, String newName, CDOBranchPoint branchPoint)
+ {
+ if (oldName == null)
+ {
+ return TagChangeKind.CREATED;
+ }
+
+ if (branchPoint == null)
+ {
+ if (newName == null)
+ {
+ return TagChangeKind.DELETED;
+ }
+
+ return TagChangeKind.RENAMED;
+ }
+
+ return TagChangeKind.MOVED;
+ }
+
+ /**
+ * @author Eike Stepper
+ * @since 4.11
+ */
+ public enum TagChangeKind
+ {
+ CREATED, RENAMED, MOVED, DELETED;
+ }
+
+ /**
* If the meaning of this type isn't clear, there really should be more of a description here...
*
* @author Eike Stepper
@@ -276,4 +347,22 @@ public interface InternalCDOBranchManager extends CDOBranchManager, ILifecycle
{
public void renameBranch(int branchID, String oldName, String newName);
}
+
+ /**
+ * If the meaning of this type isn't clear, there really should be more of a description here...
+ *
+ * @author Eike Stepper
+ * @since 4.11
+ */
+ public interface BranchLoader4 extends BranchLoader3
+ {
+ // public CDOBranchPoint changeTag(AtomicInteger modCount, String oldName, String newName, CDOBranchPoint
+ // branchPoint);
+ //
+ // public void loadTags(AtomicInteger modCount, String name, Consumer<BranchInfo> handler);
+
+ public CDOBranchPoint changeTag(AtomicInteger modCount, String oldName, String newName, CDOBranchPoint branchPoint);
+
+ public void loadTags(String name, Consumer<BranchInfo> handler);
+ }
}

Back to the top