/* * Copyright (c) 2012, 2015, 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.transfer; import org.eclipse.net4j.util.ObjectUtil; import org.eclipse.net4j.util.om.monitor.SubProgressMonitor; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author Eike Stepper * @since 4.2 */ class CDOTransferMappingImpl implements CDOTransferMapping { private final CDOTransfer transfer; private final CDOTransferElement source; private final CDOTransferMappingImpl parent; private List<CDOTransferMapping> children; private CDOTransferType transferType; private IPath relativePath; private Status status; public CDOTransferMappingImpl(CDOTransfer transfer, CDOTransferElement source, CDOTransferMapping parent, IProgressMonitor monitor) { this.transfer = transfer; this.source = source; this.parent = (CDOTransferMappingImpl)parent; relativePath = new Path(source.getName()); CDOTransferType transferType = transfer.getTransferType(source); this.transferType = transferType; if (parent != null) { this.parent.addChild(this); } try { if (isDirectory()) { CDOTransferElement[] children = source.getChildren(); monitor.beginTask("", 1 + children.length); monitor.subTask("Mapping " + source); monitor.worked(1); for (CDOTransferElement child : children) { transfer.map(child, this, new SubProgressMonitor(monitor, 1)); } } else { monitor.beginTask("", 1); monitor.subTask("Mapping " + source); monitor.worked(1); } } finally { monitor.done(); } } public CDOTransferMappingImpl(CDOTransfer transfer) { this.transfer = transfer; source = null; parent = null; transferType = CDOTransferType.FOLDER; relativePath = Path.EMPTY; } public CDOTransfer getTransfer() { return transfer; } public CDOTransferElement getSource() { return source; } public CDOTransferMapping getParent() { return parent; } public boolean isRoot() { return parent == null; } public boolean isDirectory() { if (source == null) { return true; } return source.isDirectory(); } public String getName() { return relativePath.lastSegment(); } public void setName(String name) { setRelativePath(relativePath.removeLastSegments(1).append(name)); } public IPath getRelativePath() { return relativePath; } public void setRelativePath(IPath path) { if (!ObjectUtil.equals(relativePath, path)) { IPath oldPath = relativePath; relativePath = path; unsetStatusRecursively(); transfer.relativePathChanged(this, oldPath, path); } } public void setRelativePath(String path) { setRelativePath(new Path(path)); } public void accept(Visitor visitor) { if (visitor.visit(this) && children != null) { for (CDOTransferMapping child : children) { child.accept(visitor); } } } public CDOTransferMapping[] getChildren() { if (children == null || children.isEmpty()) { return NO_CHILDREN; } CDOTransferMapping[] result = children.toArray(new CDOTransferMapping[children.size()]); Arrays.sort(result); return result; } public CDOTransferMapping getChild(IPath path) { if (path.isEmpty()) { return this; } String name = path.segment(0); for (CDOTransferMapping child : getChildren()) { if (name.equals(child.getName())) { return child.getChild(path.removeFirstSegments(1)); } } return null; } public CDOTransferMapping getChild(String path) { return getChild(new Path(path)); } private void addChild(CDOTransferMapping child) { ensureChildrenList(); if (!children.contains(child)) { children.add(child); transfer.childrenChanged(this, child, CDOTransfer.ChildrenChangedEvent.Kind.MAPPED); } } private void removeChild(CDOTransferMapping child) { if (children != null && children.remove(child)) { transfer.childrenChanged(this, child, CDOTransfer.ChildrenChangedEvent.Kind.UNMAPPED); } } private void ensureChildrenList() { if (children == null) { children = new ArrayList<CDOTransferMapping>(); } } public void unmap() { transfer.unmap(this); if (parent != null) { parent.removeChild(this); } } public CDOTransferType getTransferType() { return transferType; } public void setTransferType(CDOTransferType transferType) { if (!ObjectUtil.equals(this.transferType, transferType)) { CDOTransferType oldType = this.transferType; this.transferType = transferType; transfer.transferTypeChanged(this, oldType, transferType); } } public IPath getFullPath() { IPath relativePath = getRelativePath(); if (isRoot()) { return relativePath; } IPath path = parent.getFullPath(); return path.append(relativePath); } public Status getStatus() { if (status == null) { status = calculateStatus(); } return status; } private Status calculateStatus() { if (parent != null) { Status status = parent.getStatus(); if (status != Status.MERGE) { return status; } } CDOTransferSystem targetSystem = transfer.getTargetSystem(); IPath fullPath = getFullPath(); int lastSegment = fullPath.segmentCount(); for (int i = 1; i <= lastSegment; i++) { IPath path = fullPath.uptoSegment(i); CDOTransferElement target = targetSystem.getElement(path); if (target == null) { return Status.NEW; } boolean sourceDirectory = i == lastSegment ? isDirectory() : true; boolean targetDirectory = target.isDirectory(); if (!(sourceDirectory && targetDirectory)) { return Status.CONFLICT; } } return Status.MERGE; } private void unsetStatusRecursively() { if (status != null) { status = null; if (children != null && !children.isEmpty()) { for (CDOTransferMapping child : children) { ((CDOTransferMappingImpl)child).unsetStatusRecursively(); } } } } public CDOTransferElement getTarget() { CDOTransferSystem targetSystem = transfer.getTargetSystem(); IPath fullPath = getFullPath(); return targetSystem.getElement(fullPath); } public int compareTo(CDOTransferMapping o) { boolean directory = isDirectory(); boolean oDirectory = o.isDirectory(); if (directory != oDirectory) { return directory ? -1 : 1; } return getName().compareTo(o.getName()); } @Override public String toString() { return getFullPath().toString(); } }