/* * ==================================================================== * Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://svnkit.com/license.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * ==================================================================== */ package org.tmatesoft.svn.core.internal.wc; import java.io.OutputStream; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.SVNPropertyValue; import org.tmatesoft.svn.core.io.ISVNEditor; import org.tmatesoft.svn.core.io.diff.SVNDiffWindow; import org.tmatesoft.svn.util.SVNLogType; /** * @version 1.3 * @author TMate Software Ltd. */ public class SVNDepthFilterEditor implements ISVNEditor { private ISVNEditor myDelegate; private SVNDepth myRequestedDepth; private boolean myHasTarget; private NodeBaton myCurrentNodeBaton; private SVNDepthFilterEditor(SVNDepth depth, ISVNEditor delegate, boolean hasTarget) { myRequestedDepth = depth; myDelegate = delegate; myHasTarget = hasTarget; } public void abortEdit() throws SVNException { } public void absentDir(String path) throws SVNException { if (!myCurrentNodeBaton.myIsFiltered) { myDelegate.absentDir(path); } } public void absentFile(String path) throws SVNException { if (!myCurrentNodeBaton.myIsFiltered) { myDelegate.absentFile(path); } } public void addDir(String path, String copyFromPath, long copyFromRevision) throws SVNException { NodeBaton childNodeBaton = null; if (myCurrentNodeBaton.canEdit(SVNNodeKind.DIR)) { childNodeBaton = new NodeBaton(false, myCurrentNodeBaton.myDirDepth + 1, myCurrentNodeBaton); myDelegate.addDir(path, copyFromPath, copyFromRevision); } else { childNodeBaton = new NodeBaton(true, myCurrentNodeBaton.myDirDepth + 1, myCurrentNodeBaton); } myCurrentNodeBaton = childNodeBaton; } public void addFile(String path, String copyFromPath, long copyFromRevision) throws SVNException { NodeBaton childNodeBaton = null; if (myCurrentNodeBaton.canEdit(SVNNodeKind.FILE)) { childNodeBaton = new NodeBaton(false, myCurrentNodeBaton.myDirDepth, myCurrentNodeBaton); myDelegate.addFile(path, copyFromPath, copyFromRevision); } else { childNodeBaton = new NodeBaton(true, myCurrentNodeBaton.myDirDepth, myCurrentNodeBaton); } myCurrentNodeBaton = childNodeBaton; } public void changeDirProperty(String name, SVNPropertyValue value) throws SVNException { if (!myCurrentNodeBaton.myIsFiltered) { myDelegate.changeDirProperty(name, value); } } public void changeFileProperty(String path, String name, SVNPropertyValue value) throws SVNException { if (!myCurrentNodeBaton.myIsFiltered) { myDelegate.changeFileProperty(path, name, value); } } public void closeDir() throws SVNException { if (!myCurrentNodeBaton.myIsFiltered) { myDelegate.closeDir(); } myCurrentNodeBaton = myCurrentNodeBaton.myParentBaton; } public SVNCommitInfo closeEdit() throws SVNException { return myDelegate.closeEdit(); } public void closeFile(String path, String textChecksum) throws SVNException { if (!myCurrentNodeBaton.myIsFiltered) { myDelegate.closeFile(path, textChecksum); } myCurrentNodeBaton = myCurrentNodeBaton.myParentBaton; } public void deleteEntry(String path, long revision) throws SVNException { if (myCurrentNodeBaton.canEdit(SVNNodeKind.FILE)) { myDelegate.deleteEntry(path, revision); } } public void openDir(String path, long revision) throws SVNException { NodeBaton childNodeBaton = null; if (myCurrentNodeBaton.canEdit(SVNNodeKind.DIR)) { childNodeBaton = new NodeBaton(false, myCurrentNodeBaton.myDirDepth + 1, myCurrentNodeBaton); myDelegate.openDir(path, revision); } else { childNodeBaton = new NodeBaton(true, myCurrentNodeBaton.myDirDepth + 1, myCurrentNodeBaton); } myCurrentNodeBaton = childNodeBaton; } public void openFile(String path, long revision) throws SVNException { NodeBaton childNodeBaton = null; if (myCurrentNodeBaton.canEdit(SVNNodeKind.FILE)) { childNodeBaton = new NodeBaton(false, myCurrentNodeBaton.myDirDepth, myCurrentNodeBaton); myDelegate.openFile(path, revision); } else { childNodeBaton = new NodeBaton(true, myCurrentNodeBaton.myDirDepth, myCurrentNodeBaton); } myCurrentNodeBaton = childNodeBaton; } public void openRoot(long revision) throws SVNException { myCurrentNodeBaton = new NodeBaton(false, 1, null); myDelegate.openRoot(revision); } public void targetRevision(long revision) throws SVNException { myDelegate.targetRevision(revision); } public void applyTextDelta(String path, String baseChecksum) throws SVNException { if (!myCurrentNodeBaton.myIsFiltered) { myDelegate.applyTextDelta(path, baseChecksum); } } public OutputStream textDeltaChunk(String path, SVNDiffWindow diffWindow) throws SVNException { if (!myCurrentNodeBaton.myIsFiltered) { return myDelegate.textDeltaChunk(path, diffWindow); } return SVNFileUtil.DUMMY_OUT; } public void textDeltaEnd(String path) throws SVNException { if (!myCurrentNodeBaton.myIsFiltered) { myDelegate.textDeltaEnd(path); } } public static ISVNEditor getDepthFilterEditor(SVNDepth requestedDepth, ISVNEditor delegate, boolean hasTarget) { if (requestedDepth == SVNDepth.UNKNOWN || requestedDepth == SVNDepth.INFINITY) { return delegate; } return new SVNDepthFilterEditor(requestedDepth, delegate, hasTarget); } private class NodeBaton { boolean myIsFiltered; int myDirDepth; NodeBaton myParentBaton; public NodeBaton(boolean isFiltered, int depth, NodeBaton parent) { myIsFiltered = isFiltered; myDirDepth = depth; myParentBaton = parent; } public boolean canEdit(SVNNodeKind entryKind) throws SVNException { if (myIsFiltered) { return false; } int effectiveDepth = myDirDepth - (myHasTarget ? 1 : 0); if (myRequestedDepth == SVNDepth.EMPTY) { return effectiveDepth <= 0; } else if (myRequestedDepth == SVNDepth.FILES) { return effectiveDepth <= 0 || (entryKind == SVNNodeKind.FILE && effectiveDepth == 1); } else if (myRequestedDepth == SVNDepth.IMMEDIATES) { return effectiveDepth <= 1; } else if (myRequestedDepth == SVNDepth.INFINITY) { return true; } SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN, "depth should be a valid constant"); SVNErrorManager.error(err, SVNLogType.WC); return false; } } }