/*
* 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.netbeans.modules.php.fuel.ui.actions.gotos.statuses;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.parsing.api.ParserManager;
import org.netbeans.modules.parsing.api.ResultIterator;
import org.netbeans.modules.parsing.api.Source;
import org.netbeans.modules.parsing.api.UserTask;
import org.netbeans.modules.parsing.spi.ParseException;
import org.netbeans.modules.php.api.editor.EditorSupport;
import org.netbeans.modules.php.api.editor.PhpClass;
import org.netbeans.modules.php.api.phpmodule.PhpModule;
import org.netbeans.modules.php.api.util.FileUtils;
import org.netbeans.modules.php.api.util.StringUtils;
import org.netbeans.modules.php.editor.parser.api.Utils;
import org.netbeans.modules.php.editor.parser.astnodes.visitors.DefaultVisitor;
import org.netbeans.modules.php.fuel.modules.FuelPhpModule;
import org.netbeans.modules.php.fuel.modules.FuelPhpModule.FILE_TYPE;
import org.netbeans.modules.php.fuel.ui.actions.gotos.items.GoToItem;
import org.netbeans.modules.php.fuel.ui.actions.gotos.items.GoToItemFactory;
import org.openide.filesystems.FileObject;
import org.openide.util.Lookup;
/**
*
* @author junichi11
*/
public abstract class FuelPhpGoToStatus {
private FileObject currentFile;
private PhpModule phpModule;
private int currentOffset;
protected static final int DEFAULT_OFFSET = 0;
private static final Comparator<GoToItem> FILE_COMPARATOR = new Comparator<GoToItem>() {
@Override
public int compare(GoToItem o1, GoToItem o2) {
return o1.getFileObject().getName().compareToIgnoreCase(o2.getFileObject().getName());
}
};
FuelPhpGoToStatus() {
}
public void scan() {
if (phpModule != null && currentFile != null) {
scan(phpModule, currentFile, currentOffset);
}
}
protected abstract void scan(PhpModule phpModule, FileObject currentFile, int offset);
protected void scan(final DefaultVisitor visitor, FileObject targetFile) throws ParseException {
ParserManager.parse(Collections.singleton(Source.create(targetFile)), new UserTask() {
@Override
public void run(ResultIterator resultIterator) throws Exception {
ParserResult parseResult = (ParserResult) resultIterator.getParserResult();
visitor.scan(Utils.getRoot(parseResult));
}
});
}
// gettter and setter
public FileObject getCurrentFile() {
return currentFile;
}
public void setCurrentFile(FileObject currentFile) {
this.currentFile = currentFile;
if (currentFile != null) {
this.phpModule = PhpModule.Factory.forFileObject(currentFile);
}
}
public PhpModule getPhpModule() {
return phpModule;
}
public void setPhpModule(PhpModule phpModule) {
this.phpModule = phpModule;
}
public int getCurrentOffset() {
return currentOffset;
}
public void setCurrentOffset(int currentOffset) {
this.currentOffset = currentOffset;
}
/**
* Get all items.
*
* @return all GoToItems
*/
public List<GoToItem> getAll() {
List<GoToItem> items = new ArrayList<GoToItem>();
items.addAll(getControllers());
items.addAll(getModels());
items.addAll(getViews());
items.addAll(getViewModels());
items.addAll(getTests());
return items;
}
/**
* Get smart go to items.
*
* @return
*/
public List<GoToItem> getSmart() {
return Collections.emptyList();
}
/**
* Get GoToItems for controller.
*
* @return GoToItems if it is not empty, otherwise empty list.
*/
public List<GoToItem> getControllers() {
return Collections.emptyList();
}
/**
* Get GoToItems for controller.
*
* @return GoToItems if it is not empty, otherwise empty list.
*/
public List<GoToItem> getModels() {
return Collections.emptyList();
}
/**
* Get GoToItems for view.
*
* @return GoToItems if it is not empty, otherwise empty list.
*/
public List<GoToItem> getViews() {
return Collections.emptyList();
}
/**
* Get GoToItems for view model.
*
* @return GoToItems if it is not empty, otherwise empty list.
*/
public List<GoToItem> getViewModels() {
return Collections.emptyList();
}
/**
* Get GoToItems for test.
*
* @return GoToItems if it is not empty, otherwise empty list.
*/
public List<GoToItem> getTests() {
FuelPhpModule fuelModule = FuelPhpModule.forPhpModule(phpModule);
FileObject testsDirectory = getDirectory(FILE_TYPE.TESTS);
if (testsDirectory == null) {
return Collections.emptyList();
}
FILE_TYPE fileType = fuelModule.getFileType(currentFile);
String path = currentFile.getPath();
String relativePath = "";
int index = 0;
switch (fileType) {
case CONTROLLER:
index = path.indexOf("/controller/"); // NOI18N
break;
case MODEL:
index = path.indexOf("/model/"); // NOI18N
break;
case VIEW_MODEL:
index = path.indexOf("/view/"); // NOI18N
break;
default:
// do nothing
break;
}
if (index > 0) {
relativePath = path.substring(index);
}
if (StringUtils.isEmpty(relativePath)) {
return Collections.emptyList();
}
// get tartget
FileObject target = testsDirectory.getFileObject(relativePath);
if (target == null) {
return Collections.emptyList();
}
GoToItem goToItem = GoToItemFactory.getInstance().create(target, DEFAULT_OFFSET, ""); // NOI18N
return Collections.singletonList(goToItem);
}
/**
* Get controller items.
*
* @return
*/
public List<GoToItem> getAllControllers() {
return getGoToItems(FILE_TYPE.CONTROLLER);
}
/**
* Get model items.
*
* @return
*/
public List<GoToItem> getAllModels() {
return getGoToItems(FILE_TYPE.MODEL);
}
/**
* Get view model items.
*
* @return
*/
public List<GoToItem> getAllViewModels() {
return getGoToItems(FILE_TYPE.VIEW_MODEL);
}
/**
* Get configuration items.
*
* @return
*/
public List<GoToItem> getConfigurations() {
return getGoToItems(FILE_TYPE.CONFIG);
}
/**
* Get task items.
*
* @return
*/
public List<GoToItem> getTasks() {
return getGoToItems(FILE_TYPE.TASKS);
}
/**
* Get task items.
*
* @return
*/
public List<GoToItem> getAllTests() {
return getGoToItems(FILE_TYPE.TESTS);
}
/**
* Get GoToItems for file type.
*
* @param fileType file type
* @return GoToItems
*/
private List<GoToItem> getGoToItems(FILE_TYPE fileType) {
FileObject directory = getDirectory(fileType);
if (directory == null) {
return Collections.emptyList();
}
Enumeration<? extends FileObject> children = directory.getChildren(true);
List<GoToItem> items = new ArrayList<GoToItem>();
GoToItemFactory factory = GoToItemFactory.getInstance();
while (children.hasMoreElements()) {
FileObject child = children.nextElement();
if (FileUtils.isPhpFile(child)) {
// use EditorCookie if offset is 0 in order to open a file
items.add(factory.create(child, DEFAULT_OFFSET, null));
}
}
sort(items);
return items;
}
/**
* Get directory for file type.
*
* @param fileType
* @return directory for file type.
*/
protected FileObject getDirectory(FILE_TYPE fileType) {
FuelPhpModule fuelModule = FuelPhpModule.forPhpModule(phpModule);
return fuelModule.getDirectory(currentFile, fileType);
}
/**
* Get controller items for view and view model. Return empty list if file
* type is another type.
*
* @param fileType
* @return
*/
protected List<GoToItem> getControllers(FILE_TYPE fileType) {
if (fileType != FILE_TYPE.VIEW && fileType != FILE_TYPE.VIEW_MODEL) {
return Collections.emptyList();
}
FileObject view = getCurrentFile();
// get view directory
FileObject viewDirectory = getDirectory(fileType);
if (viewDirectory == null) {
return Collections.emptyList();
}
// create relative path to controller file
String viewDirectoryPath = viewDirectory.getPath();
String viewPath = view.getPath();
String contorllerPath = viewPath.replace(viewDirectoryPath, ""); // NOI18N
contorllerPath = contorllerPath.replace("/" + view.getNameExt(), ""); // NOI18N
// get controller directory
FileObject controllerDirectory = getDirectory(FILE_TYPE.CONTROLLER);
if (controllerDirectory == null) {
return Collections.emptyList();
}
FileObject controller = controllerDirectory.getFileObject(contorllerPath.concat(".php")); // NOI18N
// get controller
if (controller == null) {
return Collections.emptyList();
}
// infer method
EditorSupport editorSupport = Lookup.getDefault().lookup(EditorSupport.class);
Collection<PhpClass> classes = editorSupport.getClasses(controller);
int methodOffset = 0;
String methodName = ""; // NOI18N
for (PhpClass phpClass : classes) {
for (PhpClass.Method method : phpClass.getMethods()) {
if (method.getName().equals("action_" + view.getName())) { // NOI18N
methodName = method.getName();
methodOffset = method.getOffset();
break;
}
}
break;
}
GoToItemFactory factory = GoToItemFactory.getInstance();
List<GoToItem> items = new ArrayList<GoToItem>(2);
items.add(factory.create(controller, DEFAULT_OFFSET, "")); // NOI18N
if (!methodName.isEmpty()) {
items.add(factory.create(controller, methodOffset, methodName));
}
return items;
}
/**
* Sort with file name.
*
* @param items
*/
public void sort(List<GoToItem> items) {
Collections.sort(items, FILE_COMPARATOR);
}
}