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.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 Completion 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 Completion.create(); 072 } 073 } else { 074 return Completion.create(); 075 } 076 } else { 077 Collection<P> children = getChilren(f); 078 if (children == null) { 079 return Completion.create(); 080 } else { 081 return Completion.create("/", false); 082 } 083 } 084 } else if (isFile(f)) { 085 return Completion.create("", true); 086 } 087 return Completion.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 Completion.create(); 104 } 105 } else { 106 return Completion.create(); 107 } 108 } else { 109 return Completion.create(); 110 } 111 } 112 } 113 114 private Completion listDir(P dir, final String filter) throws Exception { 115 Collection<P> children = getChilren(dir); 116 if (children != null) { 117 Completion.Builder builder = Completion.builder(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 builder.add(suffix + "/", false); 126 } else { 127 // Skip it 128 } 129 } else { 130 builder.add(suffix, true); 131 } 132 } 133 } 134 return builder.build(); 135 } else { 136 return Completion.create(); 137 } 138 } 139 }