package org.springframework.ide.eclipse.boot.properties.editor.metadata; import static org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2.getHTMLContent; import javax.inject.Provider; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; 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.IType; import org.springframework.boot.configurationmetadata.Deprecation; import org.springframework.boot.configurationmetadata.ValueHint; import org.springframework.ide.eclipse.boot.properties.editor.util.TypeUtil; import org.springframework.ide.eclipse.boot.util.Log; import org.springframework.ide.eclipse.editor.support.util.HtmlSnippet; import org.springframework.ide.eclipse.editor.support.util.StringUtil; import static org.springframework.ide.eclipse.boot.properties.editor.metadata.DeprecationUtil.*; /** * Sts version of {@link ValueHint} contains similar data, but accomoates * a html snippet to be computed lazyly for the description. * <p> * This is meant to support using data pulled from JavaDoc in enums as description. * This data is a html snippet, whereas the data derived from spring-boot metadata is * just plain text. * * @author Kris De Volder */ public class StsValueHint { private static final HtmlSnippet EMPTY_DESCRIPTION = HtmlSnippet.italic("No description"); private static final Provider<HtmlSnippet> EMPTY_DESCRIPTION_PROVIDER = () -> EMPTY_DESCRIPTION; private final String value; private final Provider<HtmlSnippet> description; private final Deprecation deprecation; /** * Create a hint with a textual description. * <p> * This constructor is private. Use one of the provided * static 'create' methods instead. */ private StsValueHint(String value, Provider<HtmlSnippet> description, Deprecation deprecation) { this.value = value==null?"null":value.toString(); Assert.isLegal(!this.value.startsWith("StsValueHint")); this.description = description; this.deprecation = deprecation; } /** * Creates a hint out of an IJavaElement. */ public static StsValueHint create(String value, IJavaElement javaElement) { return new StsValueHint(value, javaDocSnippet(javaElement), DeprecationUtil.extract(javaElement)) { @Override public IJavaElement getJavaElement() { return javaElement; } }; } public static StsValueHint create(String value) { return new StsValueHint(value, EMPTY_DESCRIPTION_PROVIDER, null); } public static StsValueHint create(ValueHint hint) { return new StsValueHint(""+hint.getValue(), textSnippet(hint.getDescription()), null); } public static StsValueHint className(String fqName, TypeUtil typeUtil) { try { IJavaProject jp = typeUtil.getJavaProject(); if (jp!=null) { IType type = jp.findType(fqName, new NullProgressMonitor()); if (type!=null) { return create(type); } } } catch (Exception e) { Log.log(e); } return null; } public static StsValueHint create(IType klass) { return new StsValueHint(klass.getFullyQualifiedName(), javaDocSnippet(klass), DeprecationUtil.extract(klass)) { @Override public IJavaElement getJavaElement() { return klass; } }; } /** * Create a html snippet from a text snippet. */ private static Provider<HtmlSnippet> textSnippet(String description) { if (StringUtil.hasText(description)) { return () -> HtmlSnippet.text(description); } return EMPTY_DESCRIPTION_PROVIDER; } public String getValue() { return value; } public HtmlSnippet getDescription() { return description.get(); } public Provider<HtmlSnippet> getDescriptionProvider() { return description; } public static Provider<HtmlSnippet> javaDocSnippet(IJavaElement je) { return () -> { try { @SuppressWarnings("restriction") String htmlText = getHTMLContent(je, true); if (StringUtil.hasText(htmlText)) { return HtmlSnippet.raw(htmlText); } } catch (Exception e) { Log.log(e); } return EMPTY_DESCRIPTION; }; } @Override public String toString() { return "StsValueHint("+value+")"; } public Deprecation getDeprecation() { return deprecation; } public IJavaElement getJavaElement() { return null; } public StsValueHint prefixWith(String prefix) { StsValueHint it = this; return new StsValueHint(prefix+getValue(), description, deprecation) { @Override public IJavaElement getJavaElement() { return it.getJavaElement(); } }; } }