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.cli.completers; 021 022 import org.crsh.cli.descriptor.ParameterDescriptor; 023 import org.crsh.cli.spi.Completer; 024 import org.crsh.cli.spi.Completion; 025 026 import java.io.File; 027 import java.util.Collection; 028 029 public abstract class AbstractPathCompleter<P> implements Completer { 030 031 protected abstract String getCurrentPath() throws Exception; 032 033 protected abstract P getPath(String path) throws Exception; 034 035 protected abstract boolean exists(P path) throws Exception; 036 037 protected abstract boolean isDirectory(P path) throws Exception; 038 039 protected abstract boolean isFile(P path) throws Exception; 040 041 protected abstract Collection<P> getChilren(P path) throws Exception; 042 043 protected abstract String getName(P path) throws Exception; 044 045 public final Completion complete(ParameterDescriptor parameter, String prefix) throws Exception { 046 047 // 048 String sep = File.separator; 049 050 // Handle empty dir 051 if (!prefix.startsWith(sep)) { 052 String currentPath = getCurrentPath(); 053 054 if (!currentPath.endsWith(sep)) { 055 currentPath += sep; 056 } 057 if (prefix.length() > 0) { 058 prefix = currentPath + prefix; 059 } else { 060 prefix = currentPath; 061 } 062 } 063 064 // 065 P f = getPath(prefix); 066 067 // 068 if (exists(f)) { 069 if (isDirectory(f)) { 070 if (prefix.endsWith(sep)) { 071 Collection<P> children = getChilren(f); 072 if (children != null) { 073 if (children.size() > 0) { 074 return listDir(f, ""); 075 } else { 076 return Completion.create(); 077 } 078 } else { 079 return Completion.create(); 080 } 081 } else { 082 Collection<P> children = getChilren(f); 083 if (children == null) { 084 return Completion.create(); 085 } else { 086 return Completion.create(sep, false); 087 } 088 } 089 } else if (isFile(f)) { 090 return Completion.create("", true); 091 } 092 return Completion.create(); 093 } else { 094 int pos = prefix.lastIndexOf(sep); 095 if (pos != -1) { 096 String filter; 097 if (pos == 0) { 098 f = getPath(sep); 099 filter = prefix.substring(1); 100 } else { 101 f = getPath(prefix.substring(0, pos)); 102 filter = prefix.substring(pos + 1); 103 } 104 if (exists(f)) { 105 if (isDirectory(f)) { 106 return listDir(f, filter); 107 } else { 108 return Completion.create(); 109 } 110 } else { 111 return Completion.create(); 112 } 113 } else { 114 return Completion.create(); 115 } 116 } 117 } 118 119 private Completion listDir(P dir, final String filter) throws Exception { 120 Collection<P> children = getChilren(dir); 121 if (children != null) { 122 Completion.Builder builder = Completion.builder(filter); 123 for (P child : children) { 124 String name = getName(child); 125 if (name.startsWith(filter)) { 126 String suffix = name.substring(filter.length()); 127 if (isDirectory(child)) { 128 Collection<P> grandChildren = getChilren(child); 129 if (grandChildren != null) { 130 builder.add(suffix + File.separator, false); 131 } else { 132 // Skip it 133 } 134 } else { 135 builder.add(suffix, true); 136 } 137 } 138 } 139 return builder.build(); 140 } else { 141 return Completion.create(); 142 } 143 } 144 }