blob: 09c5b490cb4b7b91620c3e4d520ea3e718a5ad72 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.XmlSerializer;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Tag;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
/**
* @author traff
*/
public class PathMappingSettings implements Cloneable {
@NotNull
private List<PathMapping> myPathMappings;
public PathMappingSettings(@Nullable final List<PathMapping> pathMappings) {
myPathMappings = create(pathMappings);
}
@NotNull
private static List<PathMapping> create(@Nullable final List<PathMapping> mappings) {
List<PathMapping> result = ContainerUtil.newArrayList();
if (mappings != null) {
for (PathMapping m : mappings) {
if (m != null && !areBothEmpty(m.myLocalRoot, m.myRemoteRoot)) {
result.add(m);
}
}
}
return result;
}
public PathMappingSettings() {
myPathMappings = ContainerUtil.newArrayList();
}
public List<String> convertToRemote(Collection<String> paths) {
List<String> result = ContainerUtil.newArrayList();
for (String p: paths) {
result.add(convertToRemote(p));
}
return result;
}
public boolean isEmpty() {
return myPathMappings.isEmpty();
}
private static class BestMappingSelector {
private int myBestWeight = -1;
private PathMapping myBest = null;
public void consider(PathMapping mapping, int weight) {
if (weight > myBestWeight) {
myBestWeight = weight;
myBest = mapping;
}
}
@Nullable
public PathMapping get() {
return myBest;
}
}
@NotNull
public String convertToLocal(String remotePath) {
BestMappingSelector selector = new BestMappingSelector();
for (PathMapping mapping : myPathMappings) {
if (mapping.canReplaceRemote(remotePath)) {
selector.consider(mapping, mapping.getRemoteLen());
}
}
if (selector.get() != null) {
//noinspection ConstantConditions
return selector.get().mapToLocal(remotePath);
}
return remotePath;
}
public String convertToRemote(String localPath) {
BestMappingSelector selector = new BestMappingSelector();
for (PathMapping mapping : myPathMappings) {
if (mapping.canReplaceLocal(localPath)) {
selector.consider(mapping, mapping.getLocalLen());
}
}
if (selector.get() != null) {
//noinspection ConstantConditions
return selector.get().mapToRemote(localPath);
}
return localPath;
}
public void add(PathMapping mapping) {
if (areBothEmpty(mapping.myLocalRoot, mapping.myRemoteRoot)) {
return;
}
myPathMappings.add(mapping);
}
public void addMapping(String local, String remote) {
PathMapping mapping = new PathMapping(local, remote);
add(mapping);
}
public void addMappingCheckUnique(String local, String remote) {
for (PathMapping mapping: myPathMappings) {
if (pathEquals(local, mapping.getLocalRoot()) && pathEquals(remote, mapping.getRemoteRoot())) {
return;
}
}
addMapping(local, remote);
}
private static boolean pathEquals(@NotNull String path1, @NotNull String path2) {
return norm(path1).equals(norm(path2));
}
public boolean canReplaceRemote(String remotePath) {
for (PathMapping mapping : myPathMappings) {
if (mapping.canReplaceRemote(remotePath)) {
return true;
}
}
return false;
}
public boolean canReplaceLocal(String localPath) {
for (PathMapping mapping : myPathMappings) {
if (mapping.canReplaceLocal(localPath)) {
return true;
}
}
return false;
}
private static String norm(@NotNull String path) {
return FileUtil.toSystemIndependentName(path);
}
private static String normLocal(@NotNull String path) {
if (SystemInfo.isWindows) {
path = path.toLowerCase();
}
return norm(path);
}
public boolean isUseMapping() {
return !myPathMappings.isEmpty();
}
@NotNull
public List<PathMapping> getPathMappings() {
return myPathMappings;
}
public void setPathMappings(@Nullable final List<PathMapping> pathMappings) {
myPathMappings = create(pathMappings);
}
@NotNull
public static String mapToLocal(String path, String remoteRoot, String localRoot) {
if (areBothEmpty(localRoot, remoteRoot)) {
return path;
}
path = norm(path);
String remotePrefix = norm(remoteRoot);
path = path.replace(remotePrefix, norm(localRoot));
return path;
}
public static boolean areBothEmpty(String localRoot, String remoteRoot) {
return StringUtil.isEmpty(localRoot) || StringUtil.isEmpty(remoteRoot);
}
@Nullable
public static PathMappingSettings readExternal(@Nullable final Element element) {
if (element == null) {
return null;
}
final Element settingsElement = element.getChild(PathMappingSettings.class.getSimpleName());
if (settingsElement == null) {
return null;
}
return XmlSerializer.deserialize(settingsElement, PathMappingSettings.class);
}
public static void writeExternal(@Nullable final Element element, @Nullable final PathMappingSettings mappings) {
if (element == null || mappings == null || !mappings.isUseMapping()) {
return;
}
element.addContent(XmlSerializer.serialize(mappings));
}
public void addAll(@NotNull PathMappingSettings settings) {
myPathMappings.addAll(settings.getPathMappings());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PathMappingSettings settings = (PathMappingSettings)o;
if (!myPathMappings.equals(settings.myPathMappings)) return false;
return true;
}
@Override
public int hashCode() {
return myPathMappings.hashCode();
}
@Tag("mapping")
public static class PathMapping {
private String myLocalRoot;
private String myRemoteRoot;
public PathMapping() {
}
public PathMapping(String localRoot, String remoteRoot) {
myLocalRoot = normalize(localRoot);
myRemoteRoot = normalize(remoteRoot);
}
@Nullable
private static String normalize(@Nullable String path) {
if (path == null) {
return null;
}
else {
return trimSlash(FileUtil.toSystemIndependentName(path));
}
}
@Attribute("local-root")
public String getLocalRoot() {
return myLocalRoot;
}
@Attribute("remote-root")
public String getRemoteRoot() {
return myRemoteRoot;
}
private int getLocalLen() {
return myLocalRoot != null ? myLocalRoot.length() : -1;
}
private int getRemoteLen() {
return myRemoteRoot != null ? myRemoteRoot.length() : -1;
}
public void setLocalRoot(String localRoot) {
myLocalRoot = localRoot;
}
public void setRemoteRoot(String remoteRoot) {
myRemoteRoot = remoteRoot;
}
@NotNull
public String mapToLocal(@NotNull String path) {
return PathMappingSettings.mapToLocal(path, myRemoteRoot, myLocalRoot);
}
public boolean canReplaceLocal(@NotNull String path) {
if (isEmpty()) {
return false;
}
String localPrefix = normLocal(myLocalRoot);
return !localPrefix.isEmpty() && normLocal(path).startsWith(localPrefix);
}
public String mapToRemote(@NotNull String path) {
if (isEmpty()) {
return path;
}
if (canReplaceLocal(path)) {
return norm(myRemoteRoot) + norm(path).substring(normLocal(myLocalRoot).length());
}
return path;
}
private boolean isEmpty() {
return PathMappingSettings.areBothEmpty(myLocalRoot, myRemoteRoot);
}
private static String trimSlash(String s) {
return StringUtil.trimEnd(s, "/");
}
public boolean canReplaceRemote(String path) {
if (isEmpty()) {
return false;
}
path = norm(path);
String remotePrefix = norm(myRemoteRoot);
return !myRemoteRoot.isEmpty() && path.startsWith(remotePrefix);
}
@Override
public PathMapping clone() {
return new PathMapping(myLocalRoot, myRemoteRoot);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PathMapping mapping = (PathMapping)o;
if (myLocalRoot != null ? !myLocalRoot.equals(mapping.myLocalRoot) : mapping.myLocalRoot != null) return false;
if (myRemoteRoot != null ? !myRemoteRoot.equals(mapping.myRemoteRoot) : mapping.myRemoteRoot != null) return false;
return true;
}
@Override
public int hashCode() {
int result = myLocalRoot != null ? myLocalRoot.hashCode() : 0;
result = 31 * result + (myRemoteRoot != null ? myRemoteRoot.hashCode() : 0);
return result;
}
}
}