001 /*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020 package org.crsh.cmdline.completers;
021
022 import org.crsh.cmdline.ParameterDescriptor;
023 import org.crsh.cmdline.spi.Completer;
024 import org.crsh.cmdline.spi.ValueCompletion;
025
026 import java.util.Collection;
027
028 public abstract class AbstractPathCompleter<P> implements Completer {
029
030 protected abstract String getCurrentPath() throws Exception;
031
032 protected abstract P getPath(String path) throws Exception;
033
034 protected abstract boolean exists(P path) throws Exception;
035
036 protected abstract boolean isDirectory(P path) throws Exception;
037
038 protected abstract boolean isFile(P path) throws Exception;
039
040 protected abstract Collection<P> getChilren(P path) throws Exception;
041
042 protected abstract String getName(P path) throws Exception;
043
044 public final ValueCompletion complete(ParameterDescriptor<?> parameter, String prefix) throws Exception {
045
046 // Handle empty dir
047 if (!prefix.startsWith("/")) {
048 String currentPath = getCurrentPath();
049 if (!currentPath.endsWith("/")) {
050 currentPath += "/";
051 }
052 if (prefix.length() > 0) {
053 prefix = currentPath + prefix;
054 } else {
055 prefix = currentPath;
056 }
057 }
058
059 //
060 P f = getPath(prefix);
061
062 //
063 if (exists(f)) {
064 if (isDirectory(f)) {
065 if (prefix.endsWith("/")) {
066 Collection<P> children = getChilren(f);
067 if (children != null) {
068 if (children.size() > 0) {
069 return listDir(f, "");
070 } else {
071 return ValueCompletion.create();
072 }
073 } else {
074 return ValueCompletion.create();
075 }
076 } else {
077 Collection<P> children = getChilren(f);
078 if (children == null) {
079 return ValueCompletion.create();
080 } else {
081 return ValueCompletion.create("/", false);
082 }
083 }
084 } else if (isFile(f)) {
085 return ValueCompletion.create("", true);
086 }
087 return ValueCompletion.create();
088 } else {
089 int pos = prefix.lastIndexOf('/');
090 if (pos != -1) {
091 String filter;
092 if (pos == 0) {
093 f = getPath("/");
094 filter = prefix.substring(1);
095 } else {
096 f = getPath(prefix.substring(0, pos));
097 filter = prefix.substring(pos + 1);
098 }
099 if (exists(f)) {
100 if (isDirectory(f)) {
101 return listDir(f, filter);
102 } else {
103 return ValueCompletion.create();
104 }
105 } else {
106 return ValueCompletion.create();
107 }
108 } else {
109 return ValueCompletion.create();
110 }
111 }
112 }
113
114 private ValueCompletion listDir(P dir, final String filter) throws Exception {
115 Collection<P> children = getChilren(dir);
116 if (children != null) {
117 ValueCompletion map = new ValueCompletion(filter);
118 for (P child : children) {
119 String name = getName(child);
120 if (name.startsWith(filter)) {
121 String suffix = name.substring(filter.length());
122 if (isDirectory(child)) {
123 Collection<P> grandChildren = getChilren(child);
124 if (grandChildren != null) {
125 map.put(suffix + "/", false);
126 } else {
127 // Skip it
128 }
129 } else {
130 map.put(suffix, true);
131 }
132 }
133 }
134 return map;
135 } else {
136 return ValueCompletion.create();
137 }
138 }
139 }