diff options
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.common/src/org')
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); + } } |