package org.objectstyle.wolips.wodclipse.core.completion;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.ui.PlatformUI;
import org.objectstyle.wolips.bindings.api.ApiUtils;
import org.objectstyle.wolips.bindings.api.Binding;
import org.objectstyle.wolips.bindings.api.IApiBinding;
import org.objectstyle.wolips.bindings.api.Wo;
import org.objectstyle.wolips.bindings.utils.BindingReflectionUtils;
import org.objectstyle.wolips.bindings.wod.BindingValueKey;
import org.objectstyle.wolips.bindings.wod.BindingValueKeyPath;
import org.objectstyle.wolips.bindings.wod.HtmlElementCache;
import org.objectstyle.wolips.bindings.wod.TypeCache;
import org.objectstyle.wolips.core.resources.types.TypeNameCollector;
import org.objectstyle.wolips.wodclipse.core.refactoring.AddActionDialog;
import org.objectstyle.wolips.wodclipse.core.refactoring.AddActionInfo;
import org.objectstyle.wolips.wodclipse.core.refactoring.AddKeyDialog;
import org.objectstyle.wolips.wodclipse.core.refactoring.AddKeyInfo;
public class WodCompletionUtils {
public static void openBinding(String bindingValue, IApiBinding binding, IType componentType, boolean onlyIfMissing) throws CoreException {
BindingValueKeyPath bindingValueKeyPath = new BindingValueKeyPath(bindingValue, componentType, componentType.getJavaProject(), WodParserCache.getTypeCache());
if (bindingValueKeyPath.isValid()) {
if (bindingValueKeyPath.exists()) {
if (!onlyIfMissing) {
IMember member = bindingValueKeyPath.getLastBindingKey().getBindingMember();
if (member != null) {
JavaUI.openInEditor(member, true, true);
}
}
}
else if (bindingValueKeyPath.canAddKey()) {
WodCompletionUtils.addKeyOrAction(bindingValueKeyPath, binding, componentType);
}
}
}
public static String addKeyOrAction(BindingValueKeyPath bindingValueKeyPath, IApiBinding binding, IType componentType) throws CoreException {
String name = null;
if (binding.isAction()) {
AddActionInfo info = new AddActionInfo(componentType);
info.setName(bindingValueKeyPath.getOriginalKeyPath());
AddActionDialog.open(info, PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
name = info.getName();
}
else {
AddKeyInfo info = new AddKeyInfo(componentType);
info.setName(bindingValueKeyPath.getOriginalKeyPath());
AddKeyDialog.open(info, PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
name = info.getName();
}
return name;
}
protected static boolean shouldSmartInsert() {
return true;
}
public static void fillInElementNameCompletionProposals(Set<String> alreadyUsedElementNames, String token, int tokenOffset, int offset, Set<WodCompletionProposal> completionProposalsSet, boolean guessed, HtmlElementCache validElementNames) {
String partialToken = partialToken(token, tokenOffset, offset).toLowerCase();
for (String validElementName : validElementNames.elementNames()) {
if (validElementName.toLowerCase().startsWith(partialToken) && !alreadyUsedElementNames.contains(validElementName)) {
WodCompletionProposal completionProposal;
if (WodCompletionUtils.shouldSmartInsert() && guessed) {
completionProposal = new WodCompletionProposal(token, tokenOffset, offset, validElementName + " : ", validElementName, validElementName.length() + 3);
}
else {
completionProposal = new WodCompletionProposal(token, tokenOffset, offset, validElementName);
}
completionProposalsSet.add(completionProposal);
}
}
}
public static void fillInElementTypeCompletionProposals(IJavaProject project, String token, int tokenOffset, int offset, Set<WodCompletionProposal> completionProposalsSet, boolean guessed, IProgressMonitor progressMonitor) throws JavaModelException {
// Lookup type names that extend WOElement based on the current partial
// token
String partialToken = partialToken(token, tokenOffset, offset);
if (partialToken.length() > 0) {
TypeNameCollector typeNameCollector = new TypeNameCollector(project, false);
BindingReflectionUtils.findMatchingElementClassNames(partialToken, SearchPattern.R_PREFIX_MATCH, typeNameCollector, progressMonitor);
boolean includePackageName = token.indexOf('.') != -1;
Iterator<String> matchingElementClassNamesIter = typeNameCollector.typeNames();
while (matchingElementClassNamesIter.hasNext()) {
String matchingElementTypeName = matchingElementClassNamesIter.next();
String elementTypeName;
if (includePackageName) {
elementTypeName = matchingElementTypeName;
}
else {
elementTypeName = BindingReflectionUtils.getShortClassName(matchingElementTypeName);
}
WodCompletionProposal completionProposal;
IType type = typeNameCollector.getTypeForClassName(matchingElementTypeName);
if (WodCompletionUtils.shouldSmartInsert() && guessed) {
if (BindingReflectionUtils.memberIsDeprecated(type)) {
completionProposal = new WodDeprecatedCompletionProposal(token, tokenOffset, offset, elementTypeName + " {\n\t\n}", elementTypeName, elementTypeName.length() + 4);
} else {
completionProposal = new WodCompletionProposal(token, tokenOffset, offset, elementTypeName + " {\n\t\n}", elementTypeName, elementTypeName.length() + 4);
}
}
else {
if (BindingReflectionUtils.memberIsDeprecated(type)) {
completionProposal = new WodDeprecatedCompletionProposal(token, tokenOffset, offset, elementTypeName);
} else {
completionProposal = new WodCompletionProposal(token, tokenOffset, offset, elementTypeName);
}
}
completionProposalsSet.add(completionProposal);
}
}
}
public static void fillInBindingNameCompletionProposals(IJavaProject project, IType elementType, String token, int tokenOffset, int offset, Set<WodCompletionProposal> completionProposalsSet, boolean guessed, TypeCache cache) throws JavaModelException {
String partialToken = WodCompletionUtils.partialToken(token, tokenOffset, offset);
boolean showReflectionBindings = true;
// API files:
try {
Wo wo = ApiUtils.findApiModelWo(elementType, cache.getApiCache(project));
if (wo != null) {
String lowercasePartialToken = partialToken.toLowerCase();
List<Binding> bindings = wo.getBindings();
for (Binding binding : bindings) {
String bindingName = binding.getName();
String lowercaseBindingName = bindingName.toLowerCase();
if (lowercaseBindingName.startsWith(lowercasePartialToken)) {
WodCompletionProposal completionProposal;
if (WodCompletionUtils.shouldSmartInsert() && guessed) {
completionProposal = new WodCompletionProposal(token, tokenOffset, offset, bindingName + " = ", bindingName, bindingName.length() + 3);
}
else {
completionProposal = new WodCompletionProposal(token, tokenOffset, offset, bindingName);
}
completionProposalsSet.add(completionProposal);
}
}
if (bindings != null && bindings.size() > 0) {
showReflectionBindings = false;
}
}
}
catch (Throwable t) {
// It's not that big a deal ... give up on api files
t.printStackTrace();
}
if (showReflectionBindings) {
List<BindingValueKey> bindingKeys = BindingReflectionUtils.getBindingKeys(project, elementType, partialToken, false, BindingReflectionUtils.MUTATORS_ONLY, false, cache);
WodCompletionUtils._fillInCompletionProposals(bindingKeys, token, tokenOffset, offset, completionProposalsSet, false);
}
}
public static boolean fillInBindingValueCompletionProposals(IJavaProject project, IType elementType, String token, int tokenOffset, int offset, Set<WodCompletionProposal> completionProposalsSet, TypeCache cache) throws JavaModelException {
boolean checkBindingType = false;
String partialToken = partialToken(token, tokenOffset, offset);
BindingValueKeyPath bindingKeyPath = new BindingValueKeyPath(partialToken, elementType, project, cache);
List<BindingValueKey> possibleBindingKeyMatchesList = bindingKeyPath.getPartialMatchesForLastBindingKey(false);
if (possibleBindingKeyMatchesList != null) {
String bindingKeyName;
if (bindingKeyPath.getOperator() != null) {
bindingKeyName = "@" + bindingKeyPath.getOperator();
}
else {
bindingKeyName = bindingKeyPath.getLastBindingKeyName();
}
WodCompletionUtils._fillInCompletionProposals(possibleBindingKeyMatchesList, bindingKeyName, tokenOffset + partialToken.lastIndexOf('.') + 1, offset, completionProposalsSet, true);
}
// Only do binding type checks if you're on the first of a keypath ...
if (bindingKeyPath != null && bindingKeyPath.getLength() == 1) {
checkBindingType = true;
}
return checkBindingType;
}
public static String partialToken(String token, int tokenOffset, int offset) {
String partialToken;
int partialIndex = offset - tokenOffset;
if (partialIndex > token.length()) {
partialToken = token;
}
else {
partialToken = token.substring(0, offset - tokenOffset);
}
return partialToken;
}
protected static void _fillInCompletionProposals(List<BindingValueKey> bindingKeys, String token, int tokenOffset, int offset, Set<WodCompletionProposal> completionProposalsSet, boolean showUsefulSystemBindings) {
Iterator<BindingValueKey> bindingKeysIter = BindingReflectionUtils.filterSystemBindingValueKeys(bindingKeys, showUsefulSystemBindings).iterator();
while (bindingKeysIter.hasNext()) {
BindingValueKey bindingKey = bindingKeysIter.next();
WodCompletionProposal completionProposal;
if (BindingReflectionUtils.bindingPointsToDeprecatedValue(bindingKey)) {
completionProposal = new WodDeprecatedCompletionProposal(token, tokenOffset, offset, bindingKey.getBindingName());
} else {
completionProposal = new WodCompletionProposal(token, tokenOffset, offset, bindingKey.getBindingName());
}
completionProposalsSet.add(completionProposal);
}
}
}