package org.jboss.tools.batch.ui.hyperlink;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IType;
import org.eclipse.jface.text.BadLocationException;
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.osgi.util.NLS;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.jboss.tools.batch.core.BatchConstants;
import org.jboss.tools.batch.core.IBatchArtifact;
import org.jboss.tools.batch.core.IBatchProject;
import org.jboss.tools.batch.core.IBatchProperty;
import org.jboss.tools.batch.internal.core.impl.BatchProjectFactory;
import org.jboss.tools.batch.ui.BatchUIPlugin;
import org.jboss.tools.common.refactoring.MarkerResolutionUtils;
import org.jboss.tools.common.text.ext.hyperlink.OpenJavaElementHyperlink;
import org.jboss.tools.common.text.ext.hyperlink.xml.XMLJumpToHyperlink;
import org.jboss.tools.common.text.ext.util.StructuredModelWrapper;
import org.jboss.tools.common.text.ext.util.Utils;
import org.jboss.tools.common.text.ext.util.Utils.AttrNodePair;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class BatchHyperlinkDetector extends AbstractHyperlinkDetector {
@Override
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region,
boolean canShowMultipleHyperlinks) {
List<IHyperlink> links = new ArrayList<IHyperlink>();
IBatchProject batchProject = getBatchProject(MarkerResolutionUtils.getFile());
StructuredModelWrapper smw = new StructuredModelWrapper();
smw.init(textViewer.getDocument());
try {
Document xmlDocument = smw.getDocument();
if (xmlDocument == null)
return null;
AttrNodePair pair = Utils.findAttrNodePairForOffset(xmlDocument, region.getOffset());
if (pair != null && pair.getNode() != null && pair.getAttribute() != null) {
if (batchProject != null && BatchConstants.ATTR_REF.equalsIgnoreCase(pair.getAttribute().getNodeName())) { // Open Java Class for attributre @ref
IRegion sourceRegion = getAttributeValueSourceRegion(textViewer, region.getOffset(),
(Attr) pair.getAttribute());
if (sourceRegion != null) {
Collection<IBatchArtifact> artifacts = batchProject.getArtifacts(pair.getAttribute()
.getNodeValue());
for (IBatchArtifact artifact : artifacts) {
IType type = artifact.getType();
links.add(new OpenJavaElementHyperlink(NLS.bind(
BatchHyperlinkMessages.OPEN_JAVA_CLASS, type.getFullyQualifiedName()),
textViewer.getDocument(), sourceRegion, type));
}
}
} else if (BatchConstants.ATTR_NEXT.equalsIgnoreCase(pair.getAttribute().getNodeName()) // Show node with given id
|| BatchConstants.ATTR_TO.equalsIgnoreCase(pair.getAttribute().getNodeName())
|| BatchConstants.ATTR_RESTART.equalsIgnoreCase(pair.getAttribute().getNodeName())) {
IRegion sourceRegion = getAttributeValueSourceRegion(textViewer, region.getOffset(),
(Attr) pair.getAttribute());
if (sourceRegion != null) {
IndexedRegion node = findNodeWithId(xmlDocument, null, pair.getAttribute()
.getNodeValue());
if (node != null) {
Region targetRegion = new Region(node.getStartOffset(),
((IDOMElement) node).getStartEndOffset() - node.getStartOffset());
links.add(new XMLJumpToHyperlink(NLS.bind(BatchHyperlinkMessages.GO_TO_NODE,
((Node) node).getNodeName(), pair.getAttribute().getNodeValue()), textViewer
.getDocument(), sourceRegion, targetRegion));
}
}
} else if (batchProject != null // Open Java Field
&& BatchConstants.TAG_PROPERTY.equalsIgnoreCase(pair.getNode().getNodeName())
&& BatchConstants.ATTR_NAME.equalsIgnoreCase(pair.getAttribute().getNodeName())) {
IRegion sourceRegion = getAttributeValueSourceRegion(textViewer, region.getOffset(),
(Attr) pair.getAttribute());
if (sourceRegion != null) {
String ref = findAttributeInAncestors(pair.getNode(), BatchConstants.ATTR_REF);
if (ref != null) {
Collection<IBatchArtifact> artifacts = batchProject.getArtifacts(ref);
for (IBatchArtifact artifact : artifacts) {
IBatchProperty property = artifact.getProperty(pair.getAttribute()
.getNodeValue());
if (property != null) {
IField field = property.getField();
links.add(new OpenJavaElementHyperlink(NLS.bind(
BatchHyperlinkMessages.OPEN_JAVA_FIELD, field.getDeclaringType()
.getFullyQualifiedName() + "." + field.getElementName()),
textViewer.getDocument(), sourceRegion, field));
}
}
}
}
}
}
} finally {
smw.dispose();
}
if (links.size() == 0)
return null;
return (IHyperlink[]) links.toArray(new IHyperlink[links.size()]);
}
private IRegion getAttributeValueSourceRegion(ITextViewer textViewer, int offset, Attr attribute) {
IRegion sourceRegion = null;
try {
sourceRegion = Utils.getAttributeValueRegion(textViewer.getDocument(), attribute);
} catch (BadLocationException e) {
BatchUIPlugin.getDefault().logError(e);
}
if (sourceRegion != null && offset >= sourceRegion.getOffset()
&& offset <= (sourceRegion.getOffset() + sourceRegion.getLength())) {
return sourceRegion;
}
return null;
}
private IBatchProject getBatchProject(IFile file) {
if(file != null){
IBatchProject batchProject = BatchProjectFactory.getBatchProjectWithProgress(file.getProject());
if (batchProject != null && batchProject.getDeclaredBatchJobs().contains(file)) {
return batchProject;
}
}
return null;
}
private String findAttributeInAncestors(Node node, String attrName) {
if (node == null) {
return null;
}
if (node.hasAttributes()) {
NamedNodeMap attributes = node.getAttributes();
Node attr = attributes.getNamedItem(attrName);
if (attr != null) {
return attr.getNodeValue();
}
}
return findAttributeInAncestors(node.getParentNode(), attrName);
}
private IndexedRegion findNodeWithId(Node node, String nodeName, String id) {
if (node instanceof IndexedRegion && (nodeName == null || nodeName.equalsIgnoreCase(node.getNodeName()))) {
if (node.hasAttributes()) {
NamedNodeMap attributes = node.getAttributes();
Node attr = attributes.getNamedItem(BatchConstants.ATTR_ID);
if (attr != null && id.equalsIgnoreCase(attr.getNodeValue())) {
return (IndexedRegion) node;
}
}
}
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
Node child = list.item(i);
IndexedRegion result = findNodeWithId(child, nodeName, id);
if (result != null) {
return result;
}
}
return null;
}
}