/*
* Copyright (c) 2005, 2008 Sven Efftinge 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:
* Sven Efftinge - Initial API and implementation
* Artem Tikhomirov (Borland) - Migration to OCL expressions
*/
package org.eclipse.gmf.internal.xpand.expression.codeassist;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.gmf.internal.xpand.model.ExecutionContext;
import org.eclipse.gmf.internal.xpand.model.ExecutionContextImpl;
import org.eclipse.gmf.internal.xpand.util.TypeNameUtil;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.ocl.lpg.FormattingHelper;
public class TypeProposalComputer implements ProposalComputer {
private final char[] possibleTypeNameChars;
private final ProposalFactory proposalFactory;
public TypeProposalComputer(ProposalFactory factory) {
possibleTypeNameChars = new char[] {
':', '{', '}', '(', ')'
};
Arrays.sort(possibleTypeNameChars);
assert factory != null;
this.proposalFactory = factory;
}
public List<ICompletionProposal> computeProposals(final String txt, final ExecutionContext ctx) {
final String prefix = findPrefix(txt);
String[] prefixParts = prefix.split(TypeNameUtil.NS_DELIM, -1);
List<EPackage> possiblePackages = new LinkedList<EPackage>();
// XXX how about package with artificial types (e.g. various Sequence instances)?
if (prefixParts.length > 1) {
ArrayList<String> p = new ArrayList<String>(5);
p.addAll(Arrays.asList(prefixParts));
p.remove(p.size()-1);
EPackage r = ctx.getOCLEnvironment().lookupPackage(p);
if (r != null) {
possiblePackages.add(r);
}
} else {
for (Object next : ((ExecutionContextImpl) ctx).getAllVisibleModels().values()) {
if (next instanceof EPackage) {
possiblePackages.add((EPackage) next);
}
}
}
final String typeNamePrefix = prefixParts.length == 0 ? "" : prefixParts[prefixParts.length-1];
final LinkedList<ICompletionProposal> result = new LinkedList<ICompletionProposal>();
final FormattingHelper formatter = ctx.getOCLEnvironment().getFormatter();
final EPackage oclStdLibPackage = ctx.getOCLEnvironment().getOCLStandardLibrary().getOclAny().getEPackage();
for (EPackage pkg : possiblePackages) {
// XXX how about nested packages?
for (EClassifier type : pkg.getEClassifiers()) {
if (type.getName() != null && type.getName().startsWith(typeNamePrefix)) {
//String insertString = TypeNameUtil.getQualifiedName(type);
String insertString = formatter.formatQualifiedName(type);
if (!insertString.startsWith(prefix) && insertString.indexOf(prefix) > 0) {
insertString = insertString.substring(insertString.indexOf(prefix));
}
String displayStr;
// pkg == type.getPackage()
if (pkg != oclStdLibPackage) {
final String packName = formatter.formatQualifiedName(type.getEPackage());
displayStr = type.getName() + " - " + packName;
} else {
displayStr = type.getName();
}
result.add(proposalFactory.createTypeProposal(insertString, displayStr.toString(), prefix));
}
}
final String pkgQualifiedName = formatter.formatQualifiedName(pkg);
if (pkgQualifiedName.startsWith(prefix)) {
result.add(proposalFactory.createTypeProposal(pkgQualifiedName + TypeNameUtil.NS_DELIM, pkgQualifiedName, prefix));
}
}
return result;
}
/**
* is public only for testing purposes
*/
public String findPrefix(final String txt) {
final StringBuilder result = new StringBuilder();
int i = txt.length() - 1;
char c = txt.charAt(i);
while (Character.isJavaIdentifierPart(c) || Arrays.binarySearch(possibleTypeNameChars, c) >= 0) {
result.append(c);
if (i > 0) {
c = txt.charAt(--i);
} else {
break;
}
}
return result.reverse().toString();
}
}