package org.ofbiz.plugin.hyperlink;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.ofbiz.plugin.Plugin;
import org.ofbiz.plugin.model.ComponentHelper;
import org.ofbiz.plugin.model.ControllerHelper;
import org.ofbiz.plugin.model.JavaHelper;
import org.ofbiz.plugin.model.ServiceHelper;
import org.ofbiz.plugin.model.JavaHelper.GotoJavaMethodAST;
import org.ofbiz.plugin.model.OfbizModelSingleton;
import org.ofbiz.plugin.model.ScreenHelper;
import org.ofbiz.plugin.model.hyperlink.FtlHyperlink;
import org.ofbiz.plugin.model.hyperlink.HyperlinkMarker;
import org.ofbiz.plugin.model.hyperlink.HyperlinkMarkersHelper;
import org.ofbiz.plugin.ofbiz.ClasspathEntry;
import org.ofbiz.plugin.ofbiz.Component;
import org.ofbiz.plugin.ofbiz.Controller;
import org.ofbiz.plugin.ofbiz.Service;
import org.ofbiz.plugin.parser.GoToFile;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import bsh.BeanshellGotoDeclaration;
public class OfbizHyperlinkDetector extends AbstractHyperlinkDetector {
private static String RESPONSE = "response";
@Override
public IHyperlink[] detectHyperlinks(ITextViewer editor, IRegion wordRegion,
boolean arg2) {
try {
IEditorInput editorInput = Plugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getSite().getWorkbenchWindow().getActivePage().getActiveEditor().getEditorInput();
List<IHyperlink> hyperlinkMarkersToReturn = new ArrayList<IHyperlink>();
if (editorInput instanceof IFileEditorInput) {
IDocument doc = editor.getDocument();
int offset = wordRegion.getOffset();
final IRegion reg = findJavaString(doc, offset);
List<HyperlinkMarker> hyperlinkMarkers = null;
String selectedWord = doc.get(reg.getOffset(), reg.getLength());
IFile file = ((IFileEditorInput) editorInput).getFile();
String fileName = file.getName();
if (ScreenHelper.getScreenByFile(file) != null) { //if it's a screen
Node currentNode = ClassHandleXml.getCurrentNode(doc, offset);
if (currentNode != null) {
if (currentNode.getNodeName().equals("html-template")) {
String location = currentNode.getAttributes().getNamedItem("location").getNodeValue();
if (location.equals(selectedWord)) {
hyperlinkMarkers = new ArrayList<HyperlinkMarker>();
String ftlFileName = location.substring("component://".length());
Component componentByUrl = ComponentHelper.getComponentByUrl(location);
IFile fileToOpen = (IFile) ( componentByUrl.getDirectory().getFolder()).findMember(ftlFileName);
if (fileToOpen != null) {
hyperlinkMarkers.add(new FtlHyperlink(ftlFileName, fileToOpen));
}
}
} else if (currentNode.getNodeName().equals("service")) {
String location = currentNode.getAttributes().getNamedItem("service-name").getNodeValue();
if (selectedWord.equals(location)) {
hyperlinkMarkers = HyperlinkMarkersHelper.searchForServices(selectedWord);
}
} else if (currentNode.getNodeName().equals("include-form")) {
String nodeValue = currentNode.getAttributes().getNamedItem("name").getNodeValue();
String location = currentNode.getAttributes().getNamedItem("location").getNodeValue();
if (selectedWord.equals(location)) {
hyperlinkMarkers = ScreenHelper.getFormHyperlinkMarker(nodeValue, selectedWord);
}
} else if (currentNode.getNodeName().equals("include-screen")) {
String nodeValue = currentNode.getAttributes().getNamedItem("name").getNodeValue();
String location = currentNode.getAttributes().getNamedItem("location").getNodeValue();
if (selectedWord.equals(location)) {
String screenXml = selectedWord.substring("component://".length());
String formName = nodeValue;
hyperlinkMarkers = ScreenHelper.getHyperlinkMarker(formName, selectedWord);
}
} else if (currentNode.getNodeName().equals("script")) {
hyperlinkMarkers = new ArrayList<HyperlinkMarker>();
final String location = currentNode.getAttributes().getNamedItem("location").getNodeValue();
if (selectedWord.equals(location)) {
Component componentByUrl = ComponentHelper.getComponentByUrl(location);
final IFile fileToOpen = (IFile) ( componentByUrl.getDirectory().getFolder()).findMember(location.substring("component://".length()));
if (fileToOpen != null) {
hyperlinkMarkers.add(new HyperlinkMarker() {
@Override
public String getTypeLabel() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getHyperlinkText() {
return "Script: " + location;
}
@Override
public void open() {
try {
IDE.openEditor(GoToFile.getActiveWorkbenchPage(), fileToOpen);
} catch (PartInitException e) {
}
}
});
}
}
}
else {
return null;
}
}
} else if (fileName.equals("controller.xml")) {
hyperlinkMarkers = handleControllerXml(selectedWord, file,
fileName, doc, offset);
} else if(fileName.endsWith(".bsh")) {
int lineOfOffset = doc.getLineOfOffset(wordRegion.getOffset());
IRegion lineInfo = doc.getLineInformationOfOffset(wordRegion.getOffset());
int currentOffsetInLine = wordRegion.getOffset() - lineInfo.getOffset();
// currentOffsetInLine = doc.getLineOfOffset(lineOfOffset) + 1;
doc.get(lineInfo.getOffset(), lineInfo.getLength());
//expand tabs to spaces
// doc.get(arg0, arg1);
hyperlinkMarkers = BeanshellGotoDeclaration.gotoDeclaration(doc.get(0, doc.getLength()), selectedWord, currentOffsetInLine, lineOfOffset, doc);
} else {
Service serviceFile = ServiceHelper.isServiceFile(file);
if (serviceFile != null) {
// hyperlinkMarkers = HyperlinkMarkersHelper.searchForServices(selectedWord);
hyperlinkMarkers = new ArrayList<HyperlinkMarker>();
Node currentNode = ClassHandleXml.getCurrentNode(doc, offset);
if ("simple".equals(currentNode.getAttributes().getNamedItem("engine").getNodeValue())) {
if (currentNode.getAttributes().getNamedItem("invoke").getNodeValue().equals(selectedWord)) {
Component component = serviceFile.getComponent();
String location = currentNode.getAttributes().getNamedItem("location").getNodeValue();
for (ClasspathEntry classpathEntry : component.getClasspathEntries()) {
IResource findMember = component.getFolder().findMember(classpathEntry.getClasspathLocation() + "/" + location);
if (findMember != null) {
final IFile fileToOpen = (IFile) findMember;
hyperlinkMarkers.add(new HyperlinkMarker() {
@Override
public String getTypeLabel() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getHyperlinkText() {
return "Minilang";
}
@Override
public void open() {
try {
IDE.openEditor(GoToFile.getActiveWorkbenchPage(), fileToOpen);
} catch (PartInitException e) {
}
}
});
break;
}
}
}
} else if ("java".equals(currentNode.getAttributes().getNamedItem("engine").getNodeValue())) {
hyperlinkMarkers = HyperlinkMarkersHelper.searchForServices(selectedWord);
try {
String location = currentNode.getAttributes().getNamedItem("location").getNodeValue();
String invoke = currentNode.getAttributes().getNamedItem("invoke").getNodeValue();
final IType findType = OfbizModelSingleton.get().findActiveEclipseProject().getJavaproject().findType(location);
ICompilationUnit cu = findType.getCompilationUnit();
final CompilationUnit parse = JavaHelper.parse(cu);
if (parse != null) {
ASTVisitor astVisitor = new GotoJavaMethodAST(findType, hyperlinkMarkers,
parse, invoke);
parse.accept(astVisitor);
}
} catch (JavaModelException e) {
return null;
}
}
// selectedWord;
} else {
hyperlinkMarkers = HyperlinkMarkersHelper.searchForServices(selectedWord);
}
}
if (hyperlinkMarkers != null && hyperlinkMarkers.size() > 0) {
for (final HyperlinkMarker hyperlinkMarker : hyperlinkMarkers) {
hyperlinkMarkersToReturn.add(new IHyperlink() {
@Override
public void open() {
hyperlinkMarker.open();
}
@Override
public String getTypeLabel() {
return hyperlinkMarker.getTypeLabel();
}
@Override
public String getHyperlinkText() {
return hyperlinkMarker.getHyperlinkText();
}
@Override
public IRegion getHyperlinkRegion() {
IRegion hyperlinkRegion = hyperlinkMarker.getHyperlinkRegion();
if (hyperlinkRegion != null) {
return hyperlinkRegion;
}
return reg;
}
});
}
return hyperlinkMarkersToReturn.toArray(new IHyperlink[hyperlinkMarkersToReturn.size()]);
} else {
return null;
}
}
} catch (BadLocationException e) {
}
return null;
}
private List<HyperlinkMarker> handleControllerXml(final String selectedWord, final IFile file, String fileName, IDocument doc, int offset) {
final List<HyperlinkMarker> hyperlinkMarkers = new ArrayList<HyperlinkMarker>();
Node currentNode = ClassHandleXml.getCurrentNode(doc, offset);
if (currentNode != null) {
NamedNodeMap attributes = currentNode.getAttributes();
if (currentNode.getNodeName().equals(RESPONSE)) {
Node responseValue = attributes.getNamedItem("value");
if (attributes.getNamedItem("type").getNodeValue().equals("view")) {
if (responseValue.getNodeValue().equals(selectedWord)) {
hyperlinkMarkers.addAll(ControllerHelper.getHyperlinkForRequestValueView(selectedWord, file));
}
} else if (attributes.getNamedItem("type").getNodeValue().equals("request")) {
if (responseValue.getNodeValue().equals(selectedWord)) {
hyperlinkMarkers.addAll(ControllerHelper.getHyperlinkForRequestValueRequest(selectedWord, file));
}
}
} else if (currentNode.getNodeName().equals("event")) {
if (attributes.getNamedItem("type").getNodeValue().equals("service") || attributes.getNamedItem("type").getNodeValue().equals("service-multi")) {
Node responseValue = attributes.getNamedItem("invoke");
if (responseValue.getNodeValue().equals(selectedWord)) {
hyperlinkMarkers.addAll(HyperlinkMarkersHelper.searchForServices(selectedWord));
}
} else if (attributes.getNamedItem("type").getNodeValue().equals("bsf")) {
Node responseValue = attributes.getNamedItem("invoke");
if (responseValue.getNodeValue().equals(selectedWord)) {
hyperlinkMarkers.addAll(HyperlinkMarkersHelper.searchForServices(selectedWord));
}
} else if (attributes.getNamedItem("type").getNodeValue().equals("java")) {
final String invoke = attributes.getNamedItem("invoke").getNodeValue();
final String path = attributes.getNamedItem("path").getNodeValue();
if (invoke.equals(selectedWord)) {
try {
final IType findType = OfbizModelSingleton.get().findActiveEclipseProject().getJavaproject().findType(path);
ICompilationUnit cu = findType.getCompilationUnit();
final CompilationUnit parse = JavaHelper.parse(cu);
if (parse != null) {
ASTVisitor astVisitor = new GotoJavaMethodAST(findType, hyperlinkMarkers,
parse, invoke);
parse.accept(astVisitor);
}
} catch (JavaModelException e) {
return null;
}
}
}
} else if (currentNode.getNodeName().equals("view-map")) {
final String page = attributes.getNamedItem("page").getNodeValue();
if (page.equals(selectedWord)) {
if (attributes.getNamedItem("type").getNodeValue().equals("ftl")) {
Controller controller = ControllerHelper.getController(file);
IFile findMember;
if (page.contains("component://")) {
findMember = null;
} else if (page.indexOf("/") == 0) {
findMember = null;
} else {
findMember = (IFile) controller.getFile().getParent().getParent().findMember(page);
}
if (findMember != null) {
hyperlinkMarkers.add(new FtlHyperlink(page, findMember));
}
} else if (attributes.getNamedItem("type").getNodeValue().equals("screen")) {
String screenXml = page.substring(0, page.indexOf("#"));
Controller controller = ControllerHelper.getController(file);
hyperlinkMarkers.addAll(ScreenHelper.getHyperlinkMarkerForController(page, controller, screenXml));
}
}
}
}
return hyperlinkMarkers;
}
private IRegion findJavaString(IDocument document, int offset) {
int beginingPos = offset;
int endPos;
int length = 0;
try {
loop:
while (true) {
char char1 = document.getChar(beginingPos);
switch (char1) {
case '"':
case '>':
case '(':
case ',':
case '\n':
case ' ': break loop;
}
if (char1 == '"') {
break;
}
beginingPos--;
if (beginingPos == 0) {
break;
}
}
endPos = beginingPos + 1;
loop:
while (true) {
char char1 = document.getChar(endPos);
switch (char1) {
case '"':
case '<':
case ')':
case ',':
case '\n':
case ' ': break loop;
}
endPos++;
length++;
if (endPos == document.getLength()) {
break;
}
}
return new Region(beginingPos+1, length);
} catch (BadLocationException e) {
}
return null;
}
}