blob: 4a265305c24709e79f687be85ca443b5a27d9f0e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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.jdt.internal.ui.text;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.swt.graphics.Image;
import org.eclipse.jface.contentassist.ISubjectControlContentAssistProcessor;
import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
import org.eclipse.jface.contentassist.ISubjectControlContextInformationValidator;
import org.eclipse.jface.text.Assert;
import org.eclipse.jface.text.ITextViewer;
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;
/**
* A processor that aggregates the proposals of multiple other processors. When proposals are requested,
* the contained processors are queried in the order they were added to the compound object.
*
* @since 3.0
*/
public class CompoundContentAssistProcessor implements IContentAssistProcessor, ISubjectControlContentAssistProcessor {
private static class WrappedContextInformation implements IContextInformation {
private IContextInformation fInfo;
private IContentAssistProcessor fProcessor;
WrappedContextInformation(IContextInformation info, IContentAssistProcessor processor) {
fInfo= info;
fProcessor= processor;
}
/*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return fInfo.equals(obj);
}
/*
* @see org.eclipse.jface.text.contentassist.IContextInformation#getContextDisplayString()
*/
public String getContextDisplayString() {
return fInfo.getContextDisplayString();
}
/*
* @see org.eclipse.jface.text.contentassist.IContextInformation#getImage()
*/
public Image getImage() {
return fInfo.getImage();
}
/*
* @see org.eclipse.jface.text.contentassist.IContextInformation#getInformationDisplayString()
*/
public String getInformationDisplayString() {
return fInfo.getInformationDisplayString();
}
/*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return fInfo.hashCode();
}
/*
* @see java.lang.Object#toString()
*/
public String toString() {
return fInfo.toString();
}
IContentAssistProcessor getProcessor() {
return fProcessor;
}
}
private static class CompoundContentAssistValidator implements IContextInformationValidator {
private List fValidators= new ArrayList();
void add(IContextInformationValidator validator) {
fValidators.add(validator);
}
/*
* @see org.eclipse.jface.text.contentassist.IContextInformationValidator#install(org.eclipse.jface.text.contentassist.IContextInformation, org.eclipse.jface.text.ITextViewer, int)
*/
public void install(IContextInformation info, ITextViewer viewer, int documentPosition) {
IContextInformationValidator validator= getValidator(info);
if (validator != null)
validator.install(info, viewer, documentPosition);
}
IContextInformationValidator getValidator(IContextInformation info) {
if (info instanceof WrappedContextInformation) {
WrappedContextInformation wrap= (WrappedContextInformation) info;
return wrap.getProcessor().getContextInformationValidator();
}
return null;
}
/*
* @see org.eclipse.jface.text.contentassist.IContextInformationValidator#isContextInformationValid(int)
*/
public boolean isContextInformationValid(int documentPosition) {
boolean isValid= false;
for (Iterator it= fValidators.iterator(); it.hasNext();) {
IContextInformationValidator v= (IContextInformationValidator) it.next();
isValid |= v.isContextInformationValid(documentPosition);
}
return isValid;
}
}
private static class CompoundContentAssistValidatorEx extends CompoundContentAssistValidator implements ISubjectControlContextInformationValidator {
/*
* @see ISubjectControlContextInformationValidator#install(IContextInformation, IContentAssistSubjectControl, int)
*/
public void install(IContextInformation info, IContentAssistSubjectControl contentAssistSubjectControl, int documentPosition) {
IContextInformationValidator validator= getValidator(info);
if (validator instanceof ISubjectControlContextInformationValidator)
((ISubjectControlContextInformationValidator) validator).install(info, contentAssistSubjectControl, documentPosition);
}
}
private final Set fProcessors= new LinkedHashSet();
/**
* Creates a new instance.
*/
public CompoundContentAssistProcessor() {
}
/**
* Creates a new instance with one child processor.
*
* @param processor the processor to add
*/
public CompoundContentAssistProcessor(IContentAssistProcessor processor) {
add(processor);
}
/**
* Adds a processor to this compound processor.
*
* @param processor the processor to add
*/
public void add(IContentAssistProcessor processor) {
Assert.isNotNull(processor);
fProcessors.add(processor);
}
/**
* Removes a processor from this compound processor.
*
* @param processor the processor to remove
*/
public void remove(IContentAssistProcessor processor) {
fProcessors.remove(processor);
}
/**
* Creates a new instance and adds all specified processors.
*
* @param processors
*/
public CompoundContentAssistProcessor(IContentAssistProcessor[] processors) {
for (int i= 0; i < processors.length; i++) {
add(processors[i]);
}
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int)
*/
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) {
List ret= new LinkedList();
for (Iterator it= fProcessors.iterator(); it.hasNext();) {
IContentAssistProcessor p= (IContentAssistProcessor) it.next();
ICompletionProposal[] proposals= p.computeCompletionProposals(viewer, documentOffset);
if (proposals != null)
ret.addAll(Arrays.asList(proposals));
}
return (ICompletionProposal[]) ret.toArray(new ICompletionProposal[ret.size()]);
}
/**
* {@inheritDoc}
* <p>
* The returned objects are wrapper objects around the real information containers.
* </p>
*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int)
*/
public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
List ret= new LinkedList();
for (Iterator it= fProcessors.iterator(); it.hasNext();) {
IContentAssistProcessor p= (IContentAssistProcessor) it.next();
IContextInformation[] informations= p.computeContextInformation(viewer, documentOffset);
if (informations != null)
for (int i= 0; i < informations.length; i++)
ret.add(new WrappedContextInformation(informations[i], p));
}
return (IContextInformation[]) ret.toArray(new IContextInformation[ret.size()]);
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
*/
public char[] getCompletionProposalAutoActivationCharacters() {
Set ret= new LinkedHashSet();
for (Iterator it= fProcessors.iterator(); it.hasNext();) {
IContentAssistProcessor p= (IContentAssistProcessor) it.next();
char[] chars= p.getCompletionProposalAutoActivationCharacters();
if (chars != null)
for (int i = 0; i < chars.length; i++)
ret.add(new Character(chars[i]));
}
char[] chars= new char[ret.size()];
int i= 0;
for (Iterator it = ret.iterator(); it.hasNext(); i++) {
Character ch = (Character) it.next();
chars[i]= ch.charValue();
}
return chars;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
*/
public char[] getContextInformationAutoActivationCharacters() {
Set ret= new LinkedHashSet();
for (Iterator it= fProcessors.iterator(); it.hasNext();) {
IContentAssistProcessor p= (IContentAssistProcessor) it.next();
char[] chars= p.getContextInformationAutoActivationCharacters();
if (chars != null)
for (int i = 0; i < chars.length; i++)
ret.add(new Character(chars[i]));
}
char[] chars= new char[ret.size()];
int i= 0;
for (Iterator it = ret.iterator(); it.hasNext(); i++) {
Character ch = (Character) it.next();
chars[i]= ch.charValue();
}
return chars;
}
/**
* Returns the first non- <code>null</code> error message of any contained
* processor, or <code>null</code> if no processor has an error message.
*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
* @return {@inheritDoc}
*/
public String getErrorMessage() {
for (Iterator it= fProcessors.iterator(); it.hasNext();) {
IContentAssistProcessor p= (IContentAssistProcessor) it.next();
String err= p.getErrorMessage();
if (err != null)
return err;
}
return null;
}
/**
* {@inheritDoc}
* <p>
* The returned validator is a wrapper around the validators provided by the
* child processors.
* </p>
*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
*/
public IContextInformationValidator getContextInformationValidator() {
boolean hasValidator= false;
boolean hasExtension= false;
for (Iterator it= fProcessors.iterator(); it.hasNext();) {
IContentAssistProcessor p= (IContentAssistProcessor) it.next();
IContextInformationValidator v= p.getContextInformationValidator();
if (v instanceof ISubjectControlContextInformationValidator) {
hasExtension= true;
break;
} else if (v != null) {
hasValidator= true;
}
}
CompoundContentAssistValidator validator= null;
if (hasExtension)
validator= new CompoundContentAssistValidatorEx();
else if (hasValidator)
validator= new CompoundContentAssistValidator();
if (validator != null)
for (Iterator it= fProcessors.iterator(); it.hasNext();) {
IContentAssistProcessor p= (IContentAssistProcessor) it.next();
IContextInformationValidator v= p.getContextInformationValidator();
if (v != null)
validator.add(v);
}
return validator;
}
/*
* @see ISubjectControlContentAssistProcessor#computeCompletionProposals(IContentAssistSubjectControl, int)
*/
public ICompletionProposal[] computeCompletionProposals(IContentAssistSubjectControl contentAssistSubjectControl, int documentOffset) {
List ret= new LinkedList();
for (Iterator it= fProcessors.iterator(); it.hasNext();) {
Object o= it.next();
if (o instanceof ISubjectControlContentAssistProcessor) {
ISubjectControlContentAssistProcessor p= (ISubjectControlContentAssistProcessor) o;
ICompletionProposal[] proposals= p.computeCompletionProposals(contentAssistSubjectControl, documentOffset);
if (proposals != null)
ret.addAll(Arrays.asList(proposals));
}
}
return (ICompletionProposal[]) ret.toArray(new ICompletionProposal[ret.size()]);
}
/**
* {@inheritDoc}
* <p>
* The returned objects are wrapper objects around the real information containers.
* </p>
*
* @see org.eclipse.jface.contentassist.ISubjectControlContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.contentassist.IContentAssistSubject, int)
*/
public IContextInformation[] computeContextInformation(IContentAssistSubjectControl contentAssistSubjectControl, int documentOffset) {
List ret= new LinkedList();
for (Iterator it= fProcessors.iterator(); it.hasNext();) {
Object o= it.next();
if (o instanceof ISubjectControlContentAssistProcessor) {
ISubjectControlContentAssistProcessor p= (ISubjectControlContentAssistProcessor) o;
IContextInformation[] informations= p.computeContextInformation(contentAssistSubjectControl, documentOffset);
if (informations != null)
for (int i= 0; i < informations.length; i++)
ret.add(new WrappedContextInformation(informations[i], p));
}
}
return (IContextInformation[]) ret.toArray(new IContextInformation[ret.size()]);
}
}