/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2013 Oracle and/or its affiliates. All rights reserved.
*
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*
* Contributor(s):
*
* Portions Copyrighted 2013 Sun Microsystems, Inc.
*/
package org.nbphpcouncil.modules.php.yii.editor.completion.methods;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.nbphpcouncil.modules.php.yii.YiiModule;
import org.nbphpcouncil.modules.php.yii.YiiModule.PATH_ALIAS;
import org.nbphpcouncil.modules.php.yii.YiiModuleFactory;
import org.nbphpcouncil.modules.php.yii.util.YiiPathAliasSupport;
import org.nbphpcouncil.modules.php.yii.util.YiiUtils;
import org.nbphpcouncil.modules.php.yii.util.YiiViewPathSupport;
import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
import org.netbeans.modules.php.api.phpmodule.PhpModule;
import org.netbeans.modules.php.api.util.StringUtils;
import org.netbeans.modules.php.editor.api.ElementQuery;
import org.netbeans.modules.php.editor.api.ElementQueryFactory;
import org.netbeans.modules.php.editor.api.NameKind;
import org.netbeans.modules.php.editor.api.QuerySupportFactory;
import org.netbeans.modules.php.editor.api.elements.ClassElement;
import org.openide.filesystems.FileObject;
/**
*
* @author junichi11
*/
public abstract class CompletePathMethod extends Method {
private static final String SLASH = "/"; // NOI18N
private static final String DOUBLE_SLASH = "//"; // NOI18N
private static final String DOT = "."; // NOI18N
public CompletePathMethod(FileObject currentFile, PhpModule phpModule) {
super(currentFile, phpModule);
}
@Override
public List<String> getElements(String target) {
List<String> elements = new LinkedList<String>();
if (useViewPath()) {
elements.addAll(getViewPathElements(target));
}
if (usePathAlias()) {
elements.addAll(getPathAliasElements(target));
}
return elements;
}
private List<String> getViewPathElements(String target) {
List<String> elements = new LinkedList<String>();
if (target.startsWith("///")) { // NOI18N
return elements;
}
// get views directory
FileObject viewsDirectory = getViewsDirectory(target);
if (viewsDirectory != null) {
int lastSeparator = target.lastIndexOf(SLASH);
String subPath = getSubPathForView(target, lastSeparator);
String filter = getFilterForView(target, lastSeparator);
FileObject targetDirectory = null;
if (YiiViewPathSupport.isAbsoluteViewPath(target)) {
targetDirectory = viewsDirectory.getFileObject(subPath);
} else {
String controllerId = YiiUtils.getViewFolderName(currentFile.getName());
if (!StringUtils.isEmpty(controllerId)) {
targetDirectory = viewsDirectory.getFileObject(controllerId + SLASH + subPath);
}
}
// add element
if (targetDirectory != null) {
for (FileObject child : targetDirectory.getChildren()) {
String name = child.getName();
if (!name.startsWith(filter)) {
continue;
}
if (child.isFolder()) {
name = name + SLASH;
}
addElement(elements, target, subPath, name);
}
}
}
return elements;
}
private FileObject getViewsDirectory(String target) {
FileObject viewsDirectory = null;
// check absolute path
if (YiiViewPathSupport.isAppPath(target)) {
return YiiUtils.getViewsDirectory(phpModule);
}
// check in modules
if (YiiUtils.isInModules(currentFile)) {
FileObject currentModuleDirectory = YiiUtils.getCurrentModuleDirectory(currentFile);
if (currentModuleDirectory != null) {
return currentModuleDirectory.getFileObject("views"); // NOI18N
}
}
// check theme
YiiModule yiiModule = YiiModuleFactory.create(phpModule);
String themeName = yiiModule.getThemeName();
if (!StringUtils.isEmpty(themeName)) {
FileObject themesDirectory = YiiUtils.getThemesDirectory(phpModule);
if (themesDirectory != null) {
viewsDirectory = themesDirectory.getFileObject(themeName + "/views"); // NOI18N
}
} else {
viewsDirectory = YiiUtils.getViewsDirectory(phpModule);
}
return viewsDirectory;
}
private String getSubPathForView(String target, int lastSeparator) {
String subPath = ""; // NOI18N
if (lastSeparator > 1) {
if (YiiViewPathSupport.isAppPath(target)) {
subPath = target.substring(2, lastSeparator);
} else if (YiiViewPathSupport.isModulePath(target)) {
subPath = target.substring(1, lastSeparator);
} else {
subPath = target.substring(0, lastSeparator);
}
}
return subPath;
}
private String getFilterForView(String target, int lastSeparator) {
String filter;
if (lastSeparator > 1) {
filter = target.substring(lastSeparator + 1);
} else {
if (YiiViewPathSupport.isAppPath(target)) {
filter = target.substring(2);
} else if (YiiViewPathSupport.isModulePath(target)) {
filter = target.substring(1);
} else {
filter = target;
}
}
return filter;
}
private void addElement(List<String> elements, String target, String subPath, String name) {
StringBuilder sb = new StringBuilder();
if (YiiViewPathSupport.isAppPath(target)) {
sb.append(DOUBLE_SLASH);
} else if (YiiViewPathSupport.isModulePath(target)) {
sb.append(SLASH);
}
if (!StringUtils.isEmpty(subPath)) {
sb.append(subPath);
sb.append(SLASH);
}
sb.append(name);
elements.add(sb.toString());
}
private List<String> getPathAliasElements(String target) {
List<String> elements = new LinkedList<String>();
int firstDot = target.indexOf(DOT);
String pathAliasName = ""; // NOI18N
if (firstDot > 1) {
pathAliasName = target.substring(0, firstDot);
}
PATH_ALIAS pathAlias = YiiPathAliasSupport.toPathAlias(pathAliasName);
if (pathAlias != PATH_ALIAS.NONE) {
String subPath = ""; // NOI18N
String filter = ""; // NOI18N
String subPathForFind = ""; // NOI18N
// get base directory for path alias
YiiModule yiiModule = YiiModuleFactory.create(phpModule);
FileObject baseDirectory = yiiModule.getDirectory(pathAlias);
if (baseDirectory != null) {
int lastDot = target.lastIndexOf(DOT);
if (firstDot == lastDot) {
filter = target.substring(firstDot + 1);
} else {
subPath = target.substring(firstDot + 1, lastDot);
subPathForFind = subPath.replaceAll("\\.", SLASH); // NOI18N
filter = target.substring(lastDot + 1);
}
// get parent directory for completion
FileObject targetDirectory = baseDirectory.getFileObject(subPathForFind);
if (targetDirectory != null) {
// add elememts
for (FileObject child : targetDirectory.getChildren()) {
String name = child.getName();
if (!name.startsWith(filter)) {
continue;
}
if (child.isFolder()) {
name = name + DOT;
}
if (StringUtils.isEmpty(subPath)) {
elements.add(pathAliasName + DOT + name);
} else {
elements.add(pathAliasName + DOT + subPath + DOT + name);
}
}
}
}
}
if (elements.isEmpty()) {
// add default path aliases
addDefaultPathAliases(elements);
// add classes
addClasses(target, elements);
}
return elements;
}
private void addDefaultPathAliases(List<String> elements) {
for (PATH_ALIAS alias : PATH_ALIAS.values()) {
if (alias == PATH_ALIAS.NONE) {
continue;
}
elements.add(alias.getName() + DOT); // NOI18N
}
}
private void addClasses(String target, List<String> elements) {
if (useClasses()) {
ElementQuery.Index indexQuery = ElementQueryFactory.createIndexQuery(QuerySupportFactory.get(phpModule.getSourceDirectory()));
Set<ClassElement> classElements;
if (target.isEmpty()) {
classElements = indexQuery.getClasses();
} else {
classElements = indexQuery.getClasses(NameKind.create(target, QuerySupport.Kind.PREFIX));
}
for (ClassElement element : classElements) {
String name = element.getName();
if (name.startsWith(target)) {
elements.add(name);
}
}
}
}
public abstract boolean usePathAlias();
public abstract boolean useViewPath();
public abstract boolean useClasses();
}