/*******************************************************************************
* Copyright (c) 2007, 2015 David Green 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:
* David Green - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.internal.wikitext.ui.editor.help;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.eclipse.mylyn.wikitext.parser.MarkupParser;
import org.eclipse.mylyn.wikitext.parser.markup.MarkupLanguage;
import org.eclipse.mylyn.wikitext.ui.WikiText;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import com.google.common.io.Resources;
/**
* A handle to help content. HelpContent is retrieved from a resource path from a bundle. Help content is retrieved in a
* locale-specific manner, much in the same way as resource bundles are. A resource path is used with the
* {@link Locale#getDefault() default locale} to construct a search path. For example, the resource may be specified as
* <code>help/cheatSheet.textile</code> and for the locale <tt>no_NO_NY</tt> the following resource paths would be
* searched in the following order:
* <ul>
* <li><code>help/cheatSheet_no_NO_NY.textile</code></li>
* <li><code>help/cheatSheet_no_NO.textile</code></li>
* <li><code>help/cheatSheet_no.textile</code></li>
* <li><code>help/cheatSheet.textile</code></li>
* </ul>
* In this way the user is presented with the most locale-specific help resource.
*
* @author David Green
*/
public class HelpContent {
private final Bundle provider;
private final String resourcePath;
private final String resourceContentLanguage;
private final String markupLanguageName;
/**
* @param provider
* the bundle that provides the content
* @param resourcePath
* a bundle-relative path to the content
* @param resourceContentLanguage
* the markup language of the content, or null if it is HTML
* @param markupLanguage
* the markup language name for which this help content is relevant
*/
public HelpContent(Bundle provider, String resourcePath, String resourceContentLanguage, String markupLanguage) {
if (provider == null || resourcePath == null || markupLanguage == null) {
throw new IllegalArgumentException();
}
this.provider = provider;
this.resourcePath = resourcePath;
this.resourceContentLanguage = resourceContentLanguage;
this.markupLanguageName = markupLanguage;
}
/**
* The name of the markup language for which this help content is relevant
*/
public String getMarkupLanguageName() {
return markupLanguageName;
}
/**
* the bundle that provides the cheat-sheet
*/
public Bundle getProvider() {
return provider;
}
/**
* Get the help content, which may be formatted using HTML markup. If HTML markup is used, the content must be
* well-formed HTML.
*/
@SuppressWarnings("serial")
public String getContent() throws IOException {
try {
URL resource = getResource();
String content = Resources.toString(resource, StandardCharsets.UTF_8);
if (resourceContentLanguage == null || "html".equalsIgnoreCase(resourceContentLanguage)) { //$NON-NLS-1$
return content;
}
MarkupLanguage markupLanguage = WikiText.getMarkupLanguage(resourceContentLanguage);
if (markupLanguage == null) {
throw new IOException(
NLS.bind(Messages.HelpContent_noSuchMarkupLanguage, new Object[] { resourceContentLanguage }));
}
MarkupParser markupParser = new MarkupParser(markupLanguage);
return markupParser.parseToHtml(content);
} catch (final Exception e) {
throw new IOException(NLS.bind(Messages.HelpContent_cannotAccessContent,
new Object[] { provider.getSymbolicName(), resourcePath, e.getMessage() })) {
@Override
public Throwable getCause() {
return e;
}
};
}
}
private URL getResource() throws Exception {
int idx = resourcePath.lastIndexOf('.');
List<String> paths = new ArrayList<>();
if (idx != -1) {
// construct a search path based on the users locale
String basePath = resourcePath.substring(0, idx);
String extension = resourcePath.substring(idx + 1);
Locale locale = Locale.getDefault();
String language = locale.getLanguage();
String country = locale.getCountry();
String variant = locale.getVariant();
if (variant.length() > 0) {
paths.add(basePath + "_" + language + "_" + country + "_" + variant + "." + extension); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
if (country.length() > 0) {
paths.add(basePath + "_" + language + "_" + country + "." + extension); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
if (language.length() > 0) {
paths.add(basePath + "_" + language + "." + extension); //$NON-NLS-1$ //$NON-NLS-2$
}
}
paths.add(resourcePath);
for (String path : paths) {
URL resource = provider.getResource(path);
if (resource != null) {
return resource;
}
}
throw new Exception(NLS.bind(Messages.HelpContent_cannotFindResource,
new Object[] { resourcePath, provider.getSymbolicName() }));
}
}