/** * This file is part of git-as-svn. It is subject to the license terms * in the LICENSE file found in the top-level directory of this distribution * and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn, * including this file, may be copied, modified, propagated, or distributed * except according to the terms contained in the LICENSE file. */ package svnserver.repository.locks; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.tmatesoft.svn.core.SVNException; import svnserver.StringHelper; import svnserver.repository.DepthVisitor; import java.util.*; /** * Depth visitor for lock iteration. * * * * @author Artem V. Navrotskiy <bozaro@users.noreply.github.com> */ public class TreeMapLockDepthVisitor implements DepthVisitor<Iterator<LockDesc>> { @NotNull private SortedMap<String, LockDesc> locks; @NotNull private final String pathKey; public TreeMapLockDepthVisitor(@NotNull SortedMap<String, LockDesc> locks, @NotNull String pathKey) { this.pathKey = pathKey; this.locks = locks; } @NotNull @Override public Iterator<LockDesc> visitEmpty() throws SVNException { final LockDesc desc = locks.get(pathKey); return desc == null ? Collections.emptyIterator() : Arrays.asList(desc).iterator(); } @NotNull @Override public Iterator<LockDesc> visitFiles() throws SVNException { return new LockDescIterator(locks, pathKey) { @Override protected boolean filter(@NotNull Map.Entry<String, LockDesc> item) { return pathKey.equals(item.getKey()) || pathKey.equals(StringHelper.parentDir(item.getKey())); } }; } @NotNull @Override public Iterator<LockDesc> visitImmediates() throws SVNException { return visitFiles(); } @NotNull @Override public Iterator<LockDesc> visitInfinity() throws SVNException { return new LockDescIterator(locks, pathKey) { @Override protected boolean filter(@NotNull Map.Entry<String, LockDesc> item) { return true; } }; } @NotNull @Override public Iterator<LockDesc> visitUnknown() { return Collections.emptyIterator(); } private static abstract class LockDescIterator implements Iterator<LockDesc> { @NotNull private final Iterator<Map.Entry<String, LockDesc>> iterator; @NotNull private final String pathKey; @Nullable private LockDesc nextItem; public LockDescIterator(@NotNull SortedMap<String, LockDesc> locks, @NotNull String pathKey) { this.iterator = locks.tailMap(pathKey).entrySet().iterator(); this.pathKey = pathKey; this.nextItem = findNext(); } @Override public boolean hasNext() { return nextItem != null; } @Override public LockDesc next() { LockDesc result = nextItem; if (result != null) { nextItem = findNext(); } return result; } protected LockDesc findNext() { while (iterator.hasNext()) { Map.Entry<String, LockDesc> item = iterator.next(); if (StringHelper.isParentPath(pathKey, item.getKey())) { if (filter(item)) { return item.getValue(); } } } return null; } protected abstract boolean filter(@NotNull Map.Entry<String, LockDesc> item); } }