/*******************************************************************************
* Copyright (c) 2007 - 2012 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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
*
* Contributor:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.ui.texteditors.propertyeditor;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.jboss.tools.common.meta.XAttribute;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.XModelObjectConstants;
import org.jboss.tools.common.model.loaders.impl.PropertiesLoader;
import org.jboss.tools.common.model.ui.ModelUIPlugin;
import org.jboss.tools.common.model.ui.attribute.adapter.JavaClassContentAssistProvider;
import org.jboss.tools.common.model.util.EclipseJavaUtil;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
public class AbstractPropertiesContentAssistProcessor implements IContentAssistProcessor {
protected XModelObject object;
public AbstractPropertiesContentAssistProcessor() {}
public void setModelObject(XModelObject object) {
this.object = object;
}
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
int offset) {
return null;
}
public IContextInformation[] computeContextInformation(ITextViewer viewer,
int offset) {
return null;
}
public char[] getCompletionProposalAutoActivationCharacters() {
return null;
}
public char[] getContextInformationAutoActivationCharacters() {
return null;
}
public IContextInformationValidator getContextInformationValidator() {
return null;
}
public String getErrorMessage() {
return null;
}
protected class Context {
boolean inComment = false;
int offset;
int nameOffset;
int nameLength;
boolean inPropertyName = false;
String propertyName;
int valueOffset;
int valueLength;
String propertyValue;
Set<String> allProperties = new HashSet<String>();
String text;
public boolean isInComment() {
return inComment;
}
public boolean isInPropertyName() {
return inPropertyName;
}
public int getNameOffset() {
return nameOffset;
}
public int getNameLength() {
return nameLength;
}
public String getNamePrefix() {
return nameOffset < offset ? text.substring(nameOffset, offset) : ""; //$NON-NLS-1$
}
public int getValueOffset() {
return valueOffset;
}
public String getValuePrefix() {
return valueOffset < offset && valueOffset >= 0 ? text.substring(valueOffset, offset) : ""; //$NON-NLS-1$
}
public int getValueLength() {
return valueLength;
}
public String getPropertyName() {
return propertyName;
}
public boolean hasProperty(String property) {
return allProperties.contains(property) && !property.equals(propertyName);
}
public boolean isInValue() {
return !isInPropertyName() && offset >= valueOffset;
}
}
public Context getContext(ITextViewer viewer, int offset) {
Context context = new Context();
context.offset = offset;
context.text = viewer.getDocument().get();
XModelObject[] ps = object.getChildren();
for (int i = 0; i < ps.length; i++) {
String name = ps[i].getAttributeValue(XModelObjectConstants.ATTR_NAME);
context.allProperties.add(name);
}
int lineOffset = getNameOffset(viewer, offset);
context.nameOffset = lineOffset;
int valueEnd = getValueEnd(viewer, offset);
String line = viewer.getDocument().get().substring(context.nameOffset, valueEnd);
if(line.trim().startsWith("#")) {
context.inComment = true;
return context;
}
int si = PropertiesLoader.getSeparatorIndex(line);
if(si < 0) si = line.length();
if(si == line.length()) {
context.inPropertyName = true;
}
String name = line.substring(0, si).trim();
context.propertyName = name;
context.nameLength = name.length();
if(name.length() > 0) {
int b = line.indexOf(name);
if(b >= 0) {
context.nameOffset += b;
}
}
if(offset >= context.nameOffset && offset <= context.nameOffset + context.nameLength) {
context.inPropertyName = true;
}
String value = (si >= line.length()) ? "" : line.substring(si + 1, line.length());
context.valueLength = value.length();
context.propertyValue = value;
if(si < line.length()) {
context.valueOffset = lineOffset + si + 1;
int b = line.indexOf(value, si + 1);
if(b > 0) {
context.valueOffset = lineOffset + b;
}
}
return context;
}
int getNameOffset(ITextViewer viewer, int offset) {
String body = viewer.getDocument().get();
for (int i = offset - 1; i >= 0; i--) {
char c = body.charAt(i);
if(c == '\n' || c == '\r') return i + 1;
}
return 0;
}
int getValueEnd(ITextViewer viewer, int offset) {
String body = viewer.getDocument().get();
for (int i = offset; i < body.length(); i++) {
char c = body.charAt(i);
if(c == '\n' || c == '\r') return i;
}
return body.length();
}
/**
* Helper method to create property name proposal.
* @param name
* @param description
* @param context
* @return
*/
protected ICompletionProposal getNameProposal(String name, String description, Context context) {
int nameOffset = context.getNameOffset();
String namePrefix = context.getNamePrefix();
if(context.hasProperty(name)) return null;
if(!name.startsWith(namePrefix)) return null;
CompletionProposal proposal = new CompletionProposal(
name,
nameOffset,
context.getNameLength(),
name.length(),
null,
name,
null,
description);
return proposal;
}
/**
* Helper method to create property value proposal.
*
* @param value
* @param description
* @param context
* @return
*/
protected ICompletionProposal getValueProposal(String value, String description, Context context) {
int valueOffset = context.getValueOffset();
String valuePrefix = context.getValuePrefix();
if(value.length() == 0) return null;
if(!value.startsWith(valuePrefix)) return null;
CompletionProposal proposal = new CompletionProposal(
value,
valueOffset,
context.getValueLength(),
value.length(),
null,
value,
null,
description);
return proposal;
}
/**
* Helper method to get java type proposals.
*
* @param attr
* @param context
* @return
*/
protected List<ICompletionProposal> getJavaTypeContentProposals(Context context) {
return getJavaTypeContentProposals(null, context);
}
/**
* Helper method to get java type proposals.
*
* @param attr
* @param context
* @return
*/
protected List<ICompletionProposal> getJavaTypeContentProposals(XAttribute attr, Context context) {
String valuePrefix = context.getValuePrefix();
List<ICompletionProposal> result = new ArrayList<ICompletionProposal>();
JavaClassContentAssistProvider p = new JavaClassContentAssistProvider();
p.init(object, null, attr);
IContentProposalProvider pp = p.getContentProposalProvider();
IContentProposal[] ps = pp.getProposals(valuePrefix, valuePrefix.length());
IProject project = EclipseResourceUtil.getProject(object);
IJavaProject jp = EclipseResourceUtil.getJavaProject(project);
if(ps != null) for (int i = 0; i < ps.length; i++) {
String value = ps[i].getContent();
String descr = getDescription(jp, value);
CompletionProposal proposal = new CompletionProposal(
value,
context.getValueOffset(),
context.getValueLength(),
value.length(),
null,
ps[i].getLabel(),
null,
descr != null ? descr : ps[i].getDescription());
result.add(proposal);
}
return result;
}
/**
* Helper methods that gets description for java type.
* @param jp
* @param value
* @return
*/
public static String getDescription(IJavaProject jp, String typeName) {
String descr = null;
if(jp != null) try {
IType type = EclipseJavaUtil.findType(jp, typeName);
if(type != null) descr = JavadocContentAccess2.getHTMLContent(type, true);
} catch (JavaModelException e) {
//ignore
} catch (CoreException e) {
ModelUIPlugin.getDefault().logError(e);
}
return descr;
}
}