| /* |
| * Copyright (c) 2010-2012, 2014, 2016 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.internal.net4j.protocol; |
| |
| import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; |
| import org.eclipse.emf.cdo.common.id.CDOID; |
| import org.eclipse.emf.cdo.common.id.CDOIDUtil; |
| import org.eclipse.emf.cdo.common.protocol.CDODataInput; |
| import org.eclipse.emf.cdo.common.protocol.CDODataOutput; |
| import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; |
| import org.eclipse.emf.cdo.common.revision.CDORevision; |
| import org.eclipse.emf.cdo.common.revision.CDORevisionKey; |
| import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; |
| import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo; |
| |
| import org.eclipse.net4j.util.om.monitor.OMMonitor; |
| |
| import org.eclipse.emf.spi.cdo.CDOSessionProtocol.MergeDataResult; |
| |
| import java.io.IOException; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public class LoadMergeDataRequest extends CDOClientRequestWithMonitoring<MergeDataResult> |
| { |
| private CDORevisionAvailabilityInfo targetInfo; |
| |
| private CDORevisionAvailabilityInfo sourceInfo; |
| |
| private CDORevisionAvailabilityInfo targetBaseInfo; |
| |
| private CDORevisionAvailabilityInfo sourceBaseInfo; |
| |
| private int infos; |
| |
| private boolean auto; |
| |
| public LoadMergeDataRequest(CDOClientProtocol protocol, CDORevisionAvailabilityInfo targetInfo, |
| CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo, |
| CDORevisionAvailabilityInfo sourceBaseInfo) |
| { |
| super(protocol, CDOProtocolConstants.SIGNAL_LOAD_MERGE_DATA); |
| this.targetInfo = targetInfo; |
| this.sourceInfo = sourceInfo; |
| this.targetBaseInfo = targetBaseInfo; |
| this.sourceBaseInfo = sourceBaseInfo; |
| infos = 2 + (targetBaseInfo != null ? 1 : 0) + (sourceBaseInfo != null ? 1 : 0); |
| } |
| |
| @Override |
| protected void requesting(CDODataOutput out, OMMonitor monitor) throws IOException |
| { |
| out.writeInt(infos); |
| monitor.begin(infos); |
| |
| try |
| { |
| writeRevisionAvailabilityInfo(out, targetInfo, monitor.fork()); |
| writeRevisionAvailabilityInfo(out, sourceInfo, monitor.fork()); |
| |
| if (infos > 2) |
| { |
| writeRevisionAvailabilityInfo(out, targetBaseInfo, monitor.fork()); |
| } |
| |
| if (infos > 3) |
| { |
| writeRevisionAvailabilityInfo(out, sourceBaseInfo, monitor.fork()); |
| } |
| } |
| finally |
| { |
| monitor.done(); |
| } |
| } |
| |
| private void writeRevisionAvailabilityInfo(CDODataOutput out, CDORevisionAvailabilityInfo info, OMMonitor monitor) |
| throws IOException |
| { |
| CDOBranchPoint branchPoint = info.getBranchPoint(); |
| if (branchPoint != CDOBranchUtil.AUTO_BRANCH_POINT) |
| { |
| out.writeBoolean(true); |
| |
| Set<CDOID> availableRevisions = info.getAvailableRevisions().keySet(); |
| int size = availableRevisions.size(); |
| |
| out.writeCDOBranchPoint(branchPoint); |
| out.writeInt(size); |
| |
| monitor.begin(size); |
| |
| try |
| { |
| for (CDOID id : availableRevisions) |
| { |
| out.writeCDOID(id); |
| monitor.worked(); |
| } |
| } |
| finally |
| { |
| monitor.done(); |
| } |
| } |
| else |
| { |
| out.writeBoolean(false); |
| auto = true; |
| } |
| } |
| |
| @Override |
| protected MergeDataResult confirming(CDODataInput in, OMMonitor monitor) throws IOException |
| { |
| MergeDataResult result = new MergeDataResult(); |
| |
| monitor.begin(1 + infos); |
| |
| try |
| { |
| // Read IDs of objects that are changed only in target. |
| for (;;) |
| { |
| CDOID id = in.readCDOID(); |
| if (CDOIDUtil.isNull(id)) |
| { |
| break; |
| } |
| |
| result.getTargetIDs().add(id); |
| } |
| |
| // Read IDs of objects that are changed in both target and source. |
| for (;;) |
| { |
| CDOID id = in.readCDOID(); |
| if (CDOIDUtil.isNull(id)) |
| { |
| break; |
| } |
| |
| result.getTargetIDs().add(id); |
| result.getSourceIDs().add(id); |
| } |
| |
| // Read IDs of objects that are changed only in source. |
| for (;;) |
| { |
| CDOID id = in.readCDOID(); |
| if (CDOIDUtil.isNull(id)) |
| { |
| break; |
| } |
| |
| result.getSourceIDs().add(id); |
| } |
| |
| monitor.worked(); |
| |
| if (auto) |
| { |
| targetBaseInfo.setBranchPoint(in.readCDOBranchPoint()); |
| if (in.readBoolean()) |
| { |
| sourceBaseInfo.setBranchPoint(in.readCDOBranchPoint()); |
| } |
| else |
| { |
| sourceBaseInfo.setBranchPoint(targetBaseInfo.getBranchPoint()); |
| infos = 3; |
| } |
| } |
| |
| readRevisionAvailabilityInfo(in, targetInfo, result.getTargetIDs(), monitor.fork()); |
| readRevisionAvailabilityInfo(in, sourceInfo, result.getSourceIDs(), monitor.fork()); |
| |
| if (infos > 2) |
| { |
| readRevisionAvailabilityInfo(in, targetBaseInfo, result.getTargetIDs(), monitor.fork()); |
| } |
| |
| if (infos > 3) |
| { |
| readRevisionAvailabilityInfo(in, sourceBaseInfo, result.getSourceIDs(), monitor.fork()); |
| } |
| |
| result.setResultBase(CDOBranchUtil.readBranchPointOrNull(in)); |
| return result; |
| } |
| finally |
| { |
| monitor.done(); |
| } |
| } |
| |
| private void readRevisionAvailabilityInfo(CDODataInput in, CDORevisionAvailabilityInfo info, Set<CDOID> result, |
| OMMonitor monitor) throws IOException |
| { |
| int size = in.readInt(); |
| monitor.begin(size + 1); |
| |
| try |
| { |
| for (int i = 0; i < size; i++) |
| { |
| CDORevision revision; |
| if (in.readBoolean()) |
| { |
| revision = in.readCDORevision(); |
| } |
| else |
| { |
| CDORevisionKey key = in.readCDORevisionKey(); |
| revision = getRevision(key, targetInfo); |
| |
| if (revision == null && sourceInfo != null) |
| { |
| revision = getRevision(key, sourceInfo); |
| } |
| |
| if (revision == null && targetBaseInfo != null) |
| { |
| revision = getRevision(key, targetBaseInfo); |
| } |
| |
| if (revision == null) |
| { |
| throw new IllegalStateException("Missing revision: " + key); |
| } |
| } |
| |
| info.addRevision(revision); |
| monitor.worked(); |
| } |
| |
| Set<Map.Entry<CDOID, CDORevisionKey>> entrySet = info.getAvailableRevisions().entrySet(); |
| for (Iterator<Map.Entry<CDOID, CDORevisionKey>> it = entrySet.iterator(); it.hasNext();) |
| { |
| Map.Entry<CDOID, CDORevisionKey> entry = it.next(); |
| if (!result.contains(entry.getKey())) |
| { |
| it.remove(); |
| } |
| } |
| |
| monitor.worked(); |
| } |
| finally |
| { |
| monitor.done(); |
| } |
| } |
| |
| private CDORevision getRevision(CDORevisionKey key, CDORevisionAvailabilityInfo info) |
| { |
| CDORevisionKey revision = info.getRevision(key.getID()); |
| if (revision instanceof CDORevision) |
| { |
| if (key.equals(revision)) |
| { |
| return (CDORevision)revision; |
| } |
| } |
| |
| return null; |
| } |
| } |