blob: 1ca4f27d00dea816606bf44274e9446a68c532db [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsp.ui.internal.contentassist;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
import org.eclipse.jst.jsp.core.taglib.IJarRecord;
import org.eclipse.jst.jsp.core.taglib.ITLDRecord;
import org.eclipse.jst.jsp.core.taglib.ITagDirRecord;
import org.eclipse.jst.jsp.core.taglib.ITaglibDescriptor;
import org.eclipse.jst.jsp.core.taglib.ITaglibRecord;
import org.eclipse.jst.jsp.core.taglib.IURLRecord;
import org.eclipse.jst.jsp.core.taglib.TaglibIndex;
import org.eclipse.jst.jsp.ui.internal.JSPUIPlugin;
import org.eclipse.jst.jsp.ui.internal.Logger;
import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
import org.eclipse.wst.html.core.internal.contentmodel.JSP20Namespace;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
import org.eclipse.wst.sse.ui.internal.contentassist.IRelevanceConstants;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
import org.w3c.dom.Node;
/**
* @plannedfor 1.0
*/
public class JSPTaglibDirectiveContentAssistProcessor extends JSPDummyContentAssistProcessor {
public JSPTaglibDirectiveContentAssistProcessor() {
super();
}
String getSmallImageURL(ITaglibRecord taglibRecord) {
String url = null;
switch (taglibRecord.getRecordType()) {
case (ITaglibRecord.TLD) : {
ITLDRecord record = (ITLDRecord) taglibRecord;
IResource file = ResourcesPlugin.getWorkspace().getRoot().getFile(record.getPath());
if (file.getLocation() != null && record.getDescriptor().getSmallIcon().length() > 0) {
url = "platform:/resource/" + FacetModuleCoreSupport.resolve(file.getFullPath(), record.getDescriptor().getSmallIcon()); //$NON-NLS-1$
}
}
break;
case (ITaglibRecord.JAR) : {
IJarRecord record = (IJarRecord) taglibRecord;
if (record.getDescriptor().getSmallIcon().length() > 0) {
// url = "file:" +
// URIHelper.normalize(record.getDescriptor().getSmallIcon(),
// record.getLocation().toString(), "/"); //$NON-NLS-1$
}
}
break;
case (ITaglibRecord.TAGDIR) : {
}
break;
case (ITaglibRecord.URL) : {
IURLRecord record = (IURLRecord) taglibRecord;
if (record.getDescriptor().getSmallIcon().length() > 0) {
url = URIHelper.normalize(record.getDescriptor().getSmallIcon(), record.getURL().toString(), "/"); //$NON-NLS-1$
}
}
break;
}
return url;
}
protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest) {
IPath basePath = getBasePath(contentAssistRequest);
if (basePath == null)
return;
IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
// Find the attribute name for which this position should have a value
IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion();
ITextRegionList openRegions = open.getRegions();
int i = openRegions.indexOf(contentAssistRequest.getRegion());
if (i < 0)
return;
ITextRegion nameRegion = null;
while (i >= 0) {
nameRegion = openRegions.get(i--);
if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)
break;
}
String attributeName = null;
if (nameRegion != null)
attributeName = open.getText(nameRegion);
String currentValue = null;
if (contentAssistRequest.getRegion().getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
currentValue = contentAssistRequest.getText();
else
currentValue = ""; //$NON-NLS-1$
String matchString = null;
// fixups
int start = contentAssistRequest.getReplacementBeginPosition();
int length = contentAssistRequest.getReplacementLength();
if (currentValue.length() > StringUtils.strip(currentValue).length() && (currentValue.startsWith("\"") || currentValue.startsWith("'")) //$NON-NLS-1$ //$NON-NLS-2$
&& contentAssistRequest.getMatchString().length() > 0) {
matchString = currentValue.substring(1, contentAssistRequest.getMatchString().length());
}
else
matchString = currentValue.substring(0, contentAssistRequest.getMatchString().length());
boolean existingComplicatedValue = contentAssistRequest.getRegion() != null && contentAssistRequest.getRegion() instanceof ITextRegionContainer;
if (existingComplicatedValue) {
contentAssistRequest.getProposals().clear();
contentAssistRequest.getMacros().clear();
}
else {
String lowerCaseMatch = matchString.toLowerCase(Locale.US);
if (attributeName.equals(JSP11Namespace.ATTR_NAME_URI)) {
ITaglibRecord[] availableTaglibRecords = TaglibIndex.getAvailableTaglibRecords(basePath);
/*
* a simple enough way to remove duplicates (resolution at
* runtime would be nondeterministic anyway)
*/
Map uriToRecords = new HashMap();
for (int taglibRecordNumber = 0; taglibRecordNumber < availableTaglibRecords.length; taglibRecordNumber++) {
ITaglibRecord taglibRecord = availableTaglibRecords[taglibRecordNumber];
ITaglibDescriptor descriptor = taglibRecord.getDescriptor();
String uri = null;
switch (taglibRecord.getRecordType()) {
case ITaglibRecord.URL :
uri = descriptor.getURI();
uriToRecords.put(uri, taglibRecord);
break;
case ITaglibRecord.JAR : {
IPath location = ((IJarRecord) taglibRecord).getLocation();
IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(location);
IPath localContextRoot = FacetModuleCoreSupport.computeWebContentRootPath(basePath);
for (int fileNumber = 0; localContextRoot != null && fileNumber < files.length; fileNumber++) {
if (localContextRoot.isPrefixOf(files[fileNumber].getFullPath())) {
uri = IPath.SEPARATOR + files[fileNumber].getFullPath().removeFirstSegments(localContextRoot.segmentCount()).toString();
uriToRecords.put(uri, taglibRecord);
}
else {
uri = FacetModuleCoreSupport.getRuntimePath(files[fileNumber].getFullPath()).toString();
uriToRecords.put(uri, taglibRecord);
}
}
break;
}
case ITaglibRecord.TLD : {
IPath path = ((ITLDRecord) taglibRecord).getPath();
IPath localContextRoot = FacetModuleCoreSupport.computeWebContentRootPath(basePath);
if (localContextRoot.isPrefixOf(path)) {
uri = IPath.SEPARATOR + path.removeFirstSegments(localContextRoot.segmentCount()).toString();
uriToRecords.put(uri, taglibRecord);
}
else {
uri = FacetModuleCoreSupport.getRuntimePath(path).toString();
uriToRecords.put(uri, taglibRecord);
}
break;
}
}
}
/*
* use the records and their descriptors to construct
* proposals
*/
Object[] uris = uriToRecords.keySet().toArray();
for (int uriNumber = 0; uriNumber < uris.length; uriNumber++) {
String uri = uris[uriNumber].toString();
ITaglibRecord taglibRecord = (ITaglibRecord) uriToRecords.get(uri);
ITaglibDescriptor descriptor = (taglibRecord).getDescriptor();
if (uri != null && uri.length() > 0 && (matchString.length() == 0 || uri.toLowerCase(Locale.US).startsWith(lowerCaseMatch))) {
String url = getSmallImageURL(taglibRecord);
ImageDescriptor imageDescriptor = JSPUIPlugin.getInstance().getImageRegistry().getDescriptor(url);
if (imageDescriptor == null && url != null) {
URL imageURL;
try {
imageURL = new URL(url);
imageDescriptor = ImageDescriptor.createFromURL(imageURL);
JSPUIPlugin.getInstance().getImageRegistry().put(url, imageDescriptor);
}
catch (MalformedURLException e) {
Logger.logException(e);
}
}
String additionalInfo = descriptor.getDisplayName() + "<br/>" + descriptor.getDescription() + "<br/>" + descriptor.getTlibVersion();
Image image = null;
try {
image = JSPUIPlugin.getInstance().getImageRegistry().get(url);
}
catch (Exception e) {
Logger.logException(e);
}
if (image == null) {
image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
}
CustomCompletionProposal proposal = new CustomCompletionProposal("\"" + uri + "\"", start, length, uri.length() + 2, image, uri, null, additionalInfo, IRelevanceConstants.R_NONE);
contentAssistRequest.addProposal(proposal);
}
}
}
else if (attributeName.equals(JSP20Namespace.ATTR_NAME_TAGDIR)) {
ITaglibRecord[] availableTaglibRecords = TaglibIndex.getAvailableTaglibRecords(basePath);
/*
* a simple enough way to remove duplicates (resolution at
* runtime would be nondeterministic anyway)
*/
Map uriToRecords = new HashMap();
for (int taglibRecordNumber = 0; taglibRecordNumber < availableTaglibRecords.length; taglibRecordNumber++) {
ITaglibRecord taglibRecord = availableTaglibRecords[taglibRecordNumber];
String uri = null;
if (taglibRecord.getRecordType() == ITaglibRecord.TAGDIR) {
IPath path = ((ITagDirRecord) taglibRecord).getPath();
IPath localContextRoot = TaglibIndex.getContextRoot(basePath);
if (localContextRoot.isPrefixOf(path)) {
uri = IPath.SEPARATOR + path.removeFirstSegments(localContextRoot.segmentCount()).toString();
uriToRecords.put(uri, taglibRecord);
}
}
}
/*
* use the records and their descriptors to construct
* proposals
*/
Object[] uris = uriToRecords.keySet().toArray();
for (int uriNumber = 0; uriNumber < uris.length; uriNumber++) {
String uri = uris[uriNumber].toString();
ITaglibRecord taglibRecord = (ITaglibRecord) uriToRecords.get(uri);
ITaglibDescriptor descriptor = (taglibRecord).getDescriptor();
if (uri != null && uri.length() > 0 && (matchString.length() == 0 || uri.toLowerCase(Locale.US).startsWith(lowerCaseMatch))) {
String url = getSmallImageURL(taglibRecord);
ImageDescriptor imageDescriptor = null;
if (url != null) {
imageDescriptor = JSPUIPlugin.getInstance().getImageRegistry().getDescriptor(url);
}
if (imageDescriptor == null && url != null) {
URL imageURL;
try {
imageURL = new URL(url);
imageDescriptor = ImageDescriptor.createFromURL(imageURL);
JSPUIPlugin.getInstance().getImageRegistry().put(url, imageDescriptor);
}
catch (MalformedURLException e) {
Logger.logException(e);
}
}
String additionalInfo = descriptor.getDescription() + "<br/>" + descriptor.getTlibVersion();
Image image = null;
try {
image = JSPUIPlugin.getInstance().getImageRegistry().get(url);
}
catch (Exception e) {
Logger.logException(e);
}
if (image == null) {
image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
}
CustomCompletionProposal proposal = new CustomCompletionProposal("\"" + uri + "\"", start, length, uri.length() + 2, image, uri, null, additionalInfo, IRelevanceConstants.R_NONE);
contentAssistRequest.addProposal(proposal);
}
}
}
else if (attributeName.equals(JSP11Namespace.ATTR_NAME_PREFIX)) {
Node uriAttr = node.getAttributes().getNamedItem(JSP11Namespace.ATTR_NAME_URI);
String uri = null;
if (uriAttr != null) {
uri = uriAttr.getNodeValue();
ITaglibRecord[] availableTaglibRecords = TaglibIndex.getAvailableTaglibRecords(basePath);
Map prefixMap = new HashMap();
for (int taglibrecordNumber = 0; taglibrecordNumber < availableTaglibRecords.length; taglibrecordNumber++) {
ITaglibDescriptor descriptor = availableTaglibRecords[taglibrecordNumber].getDescriptor();
if (descriptor != null && descriptor.getURI() != null && descriptor.getURI().toLowerCase(Locale.US).equals(uri.toLowerCase(Locale.US))) {
String shortName = descriptor.getShortName().trim();
if (shortName.length() > 0) {
boolean valid = true;
for (int character = 0; character < shortName.length(); character++) {
valid = valid && !Character.isWhitespace(shortName.charAt(character));
}
if (valid) {
prefixMap.put(shortName, descriptor);
}
}
}
}
Object prefixes[] = prefixMap.keySet().toArray();
for (int j = 0; j < prefixes.length; j++) {
String prefix = (String) prefixes[j];
ITaglibDescriptor descriptor = (ITaglibDescriptor) prefixMap.get(prefix);
Image image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
CustomCompletionProposal proposal = new CustomCompletionProposal("\"" + prefix + "\"", start, length, prefix.length() + 2, image, prefix, null, descriptor.getDescription(), IRelevanceConstants.R_NONE);
contentAssistRequest.addProposal(proposal);
}
}
else {
Node dirAttr = node.getAttributes().getNamedItem(JSP20Namespace.ATTR_NAME_TAGDIR);
if (dirAttr != null) {
String dir = dirAttr.getNodeValue();
if (dir != null) {
ITaglibRecord record = TaglibIndex.resolve(basePath.toString(), dir, false);
if (record != null) {
ITaglibDescriptor descriptor = record.getDescriptor();
if (descriptor != null) {
String shortName = descriptor.getShortName();
Image image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
CustomCompletionProposal proposal = new CustomCompletionProposal("\"" + shortName + "\"", start, length, shortName.length() + 2, image, shortName, null, descriptor.getDescription(), IRelevanceConstants.R_NONE);
contentAssistRequest.addProposal(proposal);
}
else {
if (dir.startsWith("/WEB-INF/")) {
dir = dir.substring(9);
}
String prefix = StringUtils.replace(dir, "/", "-");
Image image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
CustomCompletionProposal proposal = new CustomCompletionProposal("\"" + prefix + "\"", start, length, prefix.length() + 2, image, prefix, null, null, IRelevanceConstants.R_NONE);
contentAssistRequest.addProposal(proposal);
}
}
}
}
}
}
}
}
/**
* Returns project request is in
*
* @param request
* @return
*/
private IPath getBasePath(ContentAssistRequest request) {
IPath baselocation = null;
if (request != null) {
IStructuredDocumentRegion region = request.getDocumentRegion();
if (region != null) {
IDocument document = region.getParentDocument();
IStructuredModel model = null;
try {
model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
if (model != null) {
String location = model.getBaseLocation();
if (location != null) {
baselocation = new Path(location);
}
}
}
finally {
if (model != null)
model.releaseFromRead();
}
}
}
return baselocation;
}
}