/*******************************************************************************
* Copyright (c) 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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.cdi.seam.config.ui.contentassist;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
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.text.IDocument;
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.ITextRegionList;
import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
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.AbstractXMLModelQueryCompletionProposalComputer;
import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentModelGenerator;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants;
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
import org.jboss.tools.cdi.core.CDICoreNature;
import org.jboss.tools.cdi.core.CDICorePlugin;
import org.jboss.tools.cdi.seam.config.core.CDISeamConfigConstants;
import org.jboss.tools.cdi.seam.config.core.CDISeamConfigExtension;
import org.jboss.tools.cdi.seam.config.core.util.Util;
import org.jboss.tools.cdi.seam.config.core.xml.SAXElement;
import org.jboss.tools.cdi.seam.config.ui.CDISeamConfigUIPlugin;
import org.jboss.tools.cdi.seam.config.ui.CDISeamConfigUiImages;
import org.jboss.tools.common.model.util.EclipseJavaUtil;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.common.xml.XMLUtilities;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
*
* @author Viacheslav Kabanovich
*
*/
public class SeamConfigXmlCompletionProposalComputer extends AbstractXMLModelQueryCompletionProposalComputer implements CDISeamConfigConstants {
static int RELEVANCE_TAG = XMLRelevanceConstants.R_STRICTLY_VALID_TAG_NAME + 100;
static int RELEVANCE_TAG_KEYWORD = RELEVANCE_TAG - 1;
static int RELEVANCE_TAG_ANNOTATION = RELEVANCE_TAG_KEYWORD - 1;
static int RELEVANCE_TAG_MEMBER = RELEVANCE_TAG_ANNOTATION - 1;
static int RELEVANCE_TAG_TYPE = RELEVANCE_TAG_MEMBER - 1;
CompletionProposalInvocationContext context;
Node currentNode;
Element parentElement;
SAXElement sax;
IFile resource;
IProject project;
IJavaProject javaProject;
CDICoreNature cdi;
CDISeamConfigExtension extension;
Map<String, String> uriByPrefix = new HashMap<String, String>();
Map<String, String> prefixByUri = new HashMap<String, String>();
String eePrefix;
Map<String, String> prefixByPackage = new HashMap<String, String>();
public List<?> computeCompletionProposals(
CompletionProposalInvocationContext context,
IProgressMonitor monitor) {
this.context = context;
currentNode = findNode();
if(currentNode instanceof IDOMElement && context.getInvocationOffset() == ((IDOMElement)currentNode).getStartOffset()) {
currentNode = currentNode.getPreviousSibling() != null ? currentNode.getPreviousSibling() : currentNode.getParentNode();
}
Node p = currentNode;
while(p != null && !(p instanceof Element)) p = p.getParentNode();
if(!(p instanceof Element)) {
// can do nothing without context of parent element.
return new ArrayList<Object>();
}
parentElement = (Element)p;
sax = buildSAXElement(currentNode);
fillNameSpaces(currentNode);
resource = findResource(getDocument());
if(resource != null) {
javaProject = EclipseResourceUtil.getJavaProject(resource.getProject());
cdi = CDICorePlugin.getCDI(resource.getProject(), true);
if(cdi != null) extension = CDISeamConfigExtension.getExtension(cdi);
}
if(!isActive()) {
return new ArrayList<Object>();
}
//compute the completion proposals
return super.computeCompletionProposals(context, monitor);
}
protected boolean isActive() {
//Cannot work without resource.
//Have nothing to suggest without packages.
//can only add in context of an element.
return (resource != null && !prefixByPackage.isEmpty() && sax != null);
}
protected IDocument getDocument() {
return context.getDocument();
}
private Node findNode() {
return (Node)ContentAssistUtils.getNodeAt(context.getViewer(), context.getInvocationOffset());
}
private IFile findResource(IDocument document) {
IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document);
try {
if (sModel != null) {
String baseLocation = sModel.getBaseLocation();
IPath location = new Path(baseLocation).makeAbsolute();
return FileBuffers.getWorkspaceFileAtLocation(location);
}
} finally {
if (sModel != null) {
sModel.releaseFromRead();
}
}
return null;
}
private SAXElement buildSAXElement(Node node) {
while(node != null && !(node instanceof Element)) {
node = node.getParentNode();
}
if(node != null) {
SAXElement sax = new SAXElement(node);
SAXElement parent = buildSAXElement(node.getParentNode());
sax.setParent(parent);
return sax;
}
return null;
}
@Override
protected void addTagInsertionProposals(
ContentAssistRequest contentAssistRequest, int childPosition,
CompletionProposalInvocationContext context) {
Set<TagData> tagData = collectTagData();
for (TagData tag: tagData) {
if(tag.isUnique() && childOtherThanCurrentNodeExists(tag.getName())) {
continue;
}
String tagText = tag.getText();
int positionAdjustment = (tagText.indexOf("><") > 0) ? tagText.indexOf("><") + 1 : tagText.length();
String displayText = tag.getName();
if(tag.getMember() instanceof IType) {
displayText += " - " + ((IType)tag.getMember()).getPackageFragment().getElementName();
}
createProposal(contentAssistRequest, tagText, displayText, positionAdjustment, tag.getMember(), tag.getRelevance());
}
}
private boolean childOtherThanCurrentNodeExists(String tagName) {
Element element = XMLUtilities.getUniqueChild((Element)parentElement, tagName);
return element != null && element != currentNode;
}
private Set<TagData> collectTagData() {
String parentElementName = sax.getLocalName();
String parentElementPrefix = sax.getPrefix();
Set<TagData> tagData = new HashSet<TagData>();
if("beans".equals(parentElementName)) {
//suggest all classes in all packages.
addTypeNames(tagData, false, false);
} else if(parentElementPrefix != null && prefixByPackage.containsValue(parentElementPrefix)) {
// If we are not in <beans>, then we have to be in context of some seam package.
IType contextType = null;
if(Util.isEntry(sax)) {
//Inside entry - only <key> and <value>
if(eePrefix != null) {
addTagData(tagData, eePrefix, KEYWORD_KEY, true, true, RELEVANCE_TAG_KEYWORD);
addTagData(tagData, eePrefix, KEYWORD_VALUE, true, true, RELEVANCE_TAG_KEYWORD);
}
} else if(Util.isValue(sax) || Util.isKey(sax)) {
//Inside value or key we can define new bean.
addTypeNames(tagData, false, true);
} else if(Util.isParameters(sax)) {
//TODO find parent method name and type, and suggest parameter types.
} else if((contextType = Util.resolveType(sax, cdi)) != null) {
//We are inside bean. Suggest members and annotations.
addTypeNames(tagData, true, false); //only annotations allowed here.
addTagData(tagData, getTagNamesForMembers(parentElementPrefix, contextType, false), RELEVANCE_TAG_MEMBER);
if(eePrefix != null) {
if(!childOtherThanCurrentNodeExists(eePrefix + ":" + KEYWORD_MODIFIES)
&& !childOtherThanCurrentNodeExists(eePrefix + ":" + KEYWORD_REPLACES)) {
addTagData(tagData, eePrefix, KEYWORD_MODIFIES, false, true, RELEVANCE_TAG_KEYWORD);
addTagData(tagData, eePrefix, KEYWORD_REPLACES, false, true, RELEVANCE_TAG_KEYWORD);
}
addTagData(tagData, eePrefix, KEYWORD_PARAMETERS, true, true, RELEVANCE_TAG_KEYWORD);
}
} else if(sax.getParent() != null && ((contextType = Util.resolveType(sax.getParent(), cdi)) != null)) {
IMember member = null;
try {
member = Util.resolveMember(contextType, sax);
} catch (JavaModelException e) {
CDISeamConfigUIPlugin.getDefault().logError(e);
}
if(member != null) {
//We are inside bean member. Suggest annotations and <value>.
addTypeNames(tagData, true, false); //only annotations allowed here.
if(eePrefix != null) {
if(member instanceof IField) {
addTagData(tagData, eePrefix, KEYWORD_VALUE, true, RELEVANCE_TAG_KEYWORD);
//should we suggest entry only for maps...
addTagData(tagData, eePrefix, KEYWORD_ENTRY, true, true, RELEVANCE_TAG_KEYWORD);
} else if(member instanceof IMethod) {
addTagData(tagData, eePrefix, KEYWORD_PARAMETERS, true, true, RELEVANCE_TAG_KEYWORD);
}
}
}
}
}
return tagData;
}
private void addTypeNames(Set<TagData> tagData, boolean annotationsOnly, boolean classesOnly) {
try {
Map<String, IMember> tagNames = getAllTagNames(annotationsOnly, classesOnly);
Set<TagData> append = new HashSet<TagData>();
addTagData(append, tagNames, annotationsOnly ? RELEVANCE_TAG_ANNOTATION : RELEVANCE_TAG_TYPE);
if(annotationsOnly) {
for (TagData tag: append) {
tag.setHasClosingTag(false);
}
}
tagData.addAll(append);
} catch (JavaModelException e) {
CDISeamConfigUIPlugin.getDefault().logError(e);
}
}
private void addTagData(Set<TagData> tagData, String prefix, String name, boolean hasClosingTag, int relevance) {
tagData.add(new TagData(prefix, name, hasClosingTag, false, relevance));
}
private void addTagData(Set<TagData> tagData, String prefix, String name, boolean hasClosingTag, boolean isUnique, int relevance) {
tagData.add(new TagData(prefix, name, hasClosingTag, isUnique, relevance));
}
private void addTagData(Set<TagData> tagData, Map<String, IMember> tagNames, int relevance) {
for (String tagName: tagNames.keySet()) {
TagData d = new TagData(tagName, relevance);
IMember m = tagNames.get(tagName);
if(m instanceof IType) {
String qn = ((IType)m).getFullyQualifiedName();
//TODO improve list of annotations that never need children.
if(QUALIFIER_ANNOTATION_TYPE_NAME.equals(qn)
|| ANY_QUALIFIER_TYPE_NAME.equals(qn)
|| DEFAULT_QUALIFIER_TYPE_NAME.equals(qn)
|| SPECIALIZES_ANNOTATION_TYPE_NAME.equals(qn)
|| DECORATOR_STEREOTYPE_TYPE_NAME.equals(qn)
|| INJECT_ANNOTATION_TYPE_NAME.equals(qn)
|| PRODUCES_ANNOTATION_TYPE_NAME.equals(qn)) {
d.setHasClosingTag(false);
}
}
d.setMember(m);
tagData.add(d);
}
}
protected void addTagNameProposals(ContentAssistRequest contentAssistRequest,
int childPosition, CompletionProposalInvocationContext context) {
IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
boolean isEnded = (node.getNodeType() != Node.TEXT_NODE) &&
node.getFirstStructuredDocumentRegion().isEnded();
if(currentNode == parentElement) {
if(parentElement.getParentNode() instanceof Element) {
parentElement = (Element)parentElement.getParentNode();
sax = sax.getParent();
}
}
String match = contentAssistRequest.getMatchString();
Set<TagData> tagData = collectTagData();
if(match != null && match.length() > 0) {
Iterator<TagData> i = tagData.iterator();
while(i.hasNext()) {
TagData d = i.next();
if(!d.getName().startsWith(match) && d.getName().indexOf(":" + match) < 0) {
i.remove();
}
}
}
for (TagData tag: tagData) {
if(tag.isUnique() && childOtherThanCurrentNodeExists(tag.getName())) {
continue;
}
String tagText = isEnded ? tag.getName() : tag.getText();
if(tagText.startsWith("<")) tagText = tagText.substring(1);
int positionAdjustment = (tagText.indexOf("><") > 0) ? tagText.indexOf("><") + 1 : tagText.length();
String displayText = tag.getName();
if(tag.getMember() instanceof IType) {
displayText += " - " + ((IType)tag.getMember()).getPackageFragment().getElementName();
}
createProposal(contentAssistRequest, tagText, displayText, positionAdjustment, tag.getMember(), tag.getRelevance());
}
}
private void createProposal(ContentAssistRequest contentAssistRequest, String tagText, String displayText, int positionAdjustment, final IMember member, int relevance) {
int begin = contentAssistRequest.getReplacementBeginPosition();
int length = contentAssistRequest.getReplacementLength();
String imagePath = XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC;
if(tagText.endsWith("\"")) { //improve that dirty hack
imagePath = XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE;
}
CustomCompletionProposal textProposal = new CustomCompletionProposal(
tagText, begin, length, positionAdjustment,
XMLEditorPluginImageHelper.getInstance().getImage(imagePath),
displayText, null, null, relevance) {
String proposedInfo = null;
public String getAdditionalProposalInfo() {
if(member != null && proposedInfo == null) {
try {
proposedInfo = JavadocContentAccess2.getHTMLContent(member, true);
if(proposedInfo == null) proposedInfo = "";
} catch (JavaModelException e) {
CDISeamConfigUIPlugin.getDefault().logError(e);
} catch (CoreException e) {
CDISeamConfigUIPlugin.getDefault().logError(e);
}
}
return proposedInfo;
}
};
contentAssistRequest.addProposal(textProposal);
}
protected void addAttributeNameProposals(
ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context) {
IType contextType = Util.resolveType(sax, cdi);
if(contextType != null) {
String match = contentAssistRequest.getMatchString();
Set<TagData> tagData = new HashSet<TagData>();
addTagData(tagData, getTagNamesForMembers(sax.getPrefix(), contextType, true), RELEVANCE_TAG_MEMBER);
for (TagData tag: tagData) {
String attrName = tag.getName().substring(tag.getName().indexOf(':') + 1);
if(parentElement.hasAttribute(attrName)) continue;
if(match != null && !attrName.startsWith(match)) continue;
String tagText = attrName + "=\"\"";
int positionAdjustment = tagText.length() - 1;
createProposal(contentAssistRequest, tagText, attrName, positionAdjustment, tag.getMember(), tag.getRelevance());
}
}
}
protected void addAttributeValueProposals(
ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context) {
IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
// Find the attribute region and name for which this position should
// have a value proposed
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;
}
}
// the name region is REQUIRED to do anything useful
if (nameRegion != null) {
String attributeName = open.getText(nameRegion);
if(attributeName.startsWith("xmlns:")) {
String match = contentAssistRequest.getMatchString();
if(match == null) {
match = "";
} else if(match.startsWith("\"") || match.startsWith("'")) {
match = match.substring(1);
}
if(match.length() == 0 || match.startsWith(URI_PREFIX) || URI_PREFIX.startsWith(match)) {
Set<String> packages = new HashSet<String>();
try {
packages = getAllPackages(javaProject);
} catch (JavaModelException e) {
CDISeamConfigUIPlugin.getDefault().logError(e);
}
packages.add(PACKAGE_EE);
for (String pkg: packages) {
String proposal = "urn:java:" + pkg;
if(match.startsWith(URI_PREFIX)) {
int q = match.lastIndexOf(":");
String pMatch = match.substring(q + 1);
if(!pkg.startsWith(pMatch)) {
continue;
}
if(pkg.indexOf('.', pMatch.length() + 1) >= 0) {
continue;
}
proposal = match.substring(0, q + 1) + pkg;
} else {
if(pkg.indexOf('.') > 0) continue;
}
int positionAdjustment = proposal.length();
String displayText = pkg;
createValueProposal(contentAssistRequest, proposal, displayText, positionAdjustment, null, 1000);
}
}
}
}
}
private void createValueProposal(ContentAssistRequest contentAssistRequest, String tagText, String displayText, int positionAdjustment, IMember member, int relevance) {
int begin = contentAssistRequest.getReplacementBeginPosition() + 1;
String match = contentAssistRequest.getMatchString();
int length = match == null || match.length() == 0 ? 0 : match.length() - 1;
String proposedInfo = null;
CustomCompletionProposal textProposal = new CustomCompletionProposal(
tagText, begin, length, positionAdjustment,
CDISeamConfigUiImages.PACKAGE_IMAGE,
displayText, null, proposedInfo, relevance) {
// we make it our own type to filter from WTP's proposals
};
contentAssistRequest.addProposal(textProposal);
}
@Override
protected XMLContentModelGenerator getContentGenerator() {
return new XMLContentModelGenerator();
}
@Override
protected boolean validModelQueryNode(CMNode node) {
return false;
}
static String XMLNS_PREFIX = "xmlns:";
private void fillNameSpaces(Node node) {
uriByPrefix.clear();
prefixByUri.clear();
prefixByPackage.clear();
eePrefix = null;
while(node != null) {
if(node instanceof Element) {
Element element = (Element)node;
NamedNodeMap as = element.getAttributes();
for (int i = 0; i < as.getLength(); i++) {
Node a = as.item(i);
String nm = a.getNodeName();
if(nm.startsWith(XMLNS_PREFIX)) {
String prefix = nm.substring(XMLNS_PREFIX.length());
String uri = a.getNodeValue();
if(uri != null) {
uriByPrefix.put(prefix, uri);
prefixByUri.put(uri, prefix);
String[] packages = Util.getPackages(uri);
for (String pkg: packages) {
prefixByPackage.put(pkg, prefix);
}
}
}
}
}
eePrefix = prefixByPackage.get(PACKAGE_EE);
node = node.getParentNode();
}
}
Map<String, IMember> getAllTagNames(boolean annotationsOnly, boolean classesOnly) throws JavaModelException {
Map<String, IMember> result = new HashMap<String, IMember>();
for (String packageName: prefixByPackage.keySet()) {
String prefix = prefixByPackage.get(packageName);
Map<String, IMember> typeNames = findTypeNamesByPackage(javaProject, packageName, annotationsOnly, classesOnly);
for (String typeName: typeNames.keySet()) {
result.put(prefix + ":" + typeName, typeNames.get(typeName));
}
}
return result;
}
Map<String, IMember> getTypeNamesByPrefix(String prefix, boolean annotationsOnly, boolean classesOnly) throws JavaModelException {
Map<String, IMember> result = new HashMap<String, IMember>();
String uri = uriByPrefix.get(prefix);
for (String packageName: Util.getPackages(uri)) {
result.putAll(findTypeNamesByPackage(javaProject, packageName, annotationsOnly, classesOnly));
}
return result;
}
public static Map<String, IMember> findTypeNamesByPackage(IJavaProject javaProject, String packageName, boolean annotationsOnly, boolean classesOnly) throws JavaModelException {
Map<String, IMember> result = new HashMap<String, IMember>();
if(PACKAGE_EE.equals(packageName)) {
for (String name: Util.EE_TYPES.keySet()) {
String cls = Util.EE_TYPES.get(name);
IType t = EclipseJavaUtil.findType(javaProject, cls);
if(accept(t, annotationsOnly, classesOnly)) result.put(name, t);
}
for (String name: Util.EE_TYPES_30.keySet()) {
String cls = Util.EE_TYPES_30.get(name);
IType t = EclipseJavaUtil.findType(javaProject, cls);
if(accept(t, annotationsOnly, classesOnly)) result.put(name, t);
}
} else if(javaProject != null) {
IPackageFragmentRoot[] rs = javaProject.getAllPackageFragmentRoots();
for (IPackageFragmentRoot r: rs) {
IPackageFragment pkg = r.getPackageFragment(packageName);
if(pkg != null && pkg.exists()) {
ICompilationUnit[] units = pkg.getCompilationUnits();
for (ICompilationUnit u: units) {
IType[] ts = u.getTypes();
for (IType t: ts) if(accept(t, annotationsOnly, classesOnly)) result.put(t.getElementName(), t);
}
IClassFile[] cs = pkg.getClassFiles();
for (IClassFile cls: cs) {
if(accept(cls.getType(), annotationsOnly, classesOnly)) result.put(cls.getType().getElementName(), cls.getType());
}
}
}
}
return result;
}
public static Set<String> getAllPackages(IJavaProject javaProject) throws JavaModelException {
Set<String> result = new HashSet<String>();
IPackageFragmentRoot[] rs = javaProject.getAllPackageFragmentRoots();
for (IPackageFragmentRoot r: rs) {
IJavaElement[] cs = r.getChildren();
for (IJavaElement c: cs) {
if(c instanceof IPackageFragment) {
result.add(((IPackageFragment)c).getElementName());
}
}
}
return result;
}
private static boolean accept(IType type, boolean annotationOnly, boolean classesOnly) throws JavaModelException {
return (type != null) && (!annotationOnly || type.isAnnotation() && (!classesOnly || !type.isInterface()));
}
private Map<String, IMember> getTagNamesForMembers(String prefix, IType type, boolean fieldsOnly) {
Map<String, IMember> result = new HashMap<String, IMember>();
try {
IField[] fs = type.getFields();
for (IField f: fs) {
result.put(prefix + ":" + f.getElementName(), f);
}
if(!fieldsOnly || type.isAnnotation()) {
IMethod[] ms = type.getMethods();
for (IMethod m: ms) {
result.put(prefix + ":" + m.getElementName(), m);
}
}
} catch (JavaModelException e) {
CDISeamConfigUIPlugin.getDefault().logError(e);
}
return result;
}
}