Java tutorial
/** * Created by Kay Lerch (https://twitter.com/KayLerch) * * Contribute to https://github.com/KayLerch/alexa-skills-kit-tellask-java * * Attached license applies. * This source is licensed under GNU GENERAL PUBLIC LICENSE Version 3 as of 29 June 2007 */ package io.klerch.alexa.tellask.util.resource; import io.klerch.alexa.tellask.schema.UtteranceReader; import org.apache.commons.lang3.Validate; import java.io.InputStream; import java.net.URL; /** * An implementation to the UtteranceReader interface which encapsulates * logic of reading out a set of utterances from the the class-loader. Thus * it expects YAML files (utterances.yml) in the resources-directory of your * skill project. It looks for this YAML file in directories whose name equals the locale coming in * from the speechlet request (e.g. /en-US/utterances.yml). You could provide * a leading path over the constructor to have your files stored like e.g. * /my/leading/path/en-US/utterances.yml). In addition by overriding the resourceLocation * you could add some trailing path to have something like this * /my/leading/path/en-US/my/trailing/path/utterances.yml * That said it is possible to provide utterances for different locales just * by having those files in the right place. */ public class ResourceUtteranceReader implements UtteranceReader { /** * The default resource location. This is just the trailing portion of * the qualified resource path. */ public static final String DEFAULT_RESOURCE_LOCATION = "/utterances.yml"; /** * The default leading path. This is the portion in front of the locale * folder. */ public static final String DEFAULT_LEADING_PATH = "/"; private final String leadingPath; private String resourceLocation = DEFAULT_RESOURCE_LOCATION; /** * New reader for classloader-resources. Note that a * fully qualified path is a concatenation of the leading path (set in the constructor), * the locale (given to the read-method) and the trailing resource location containing the actual filename (can be overridden * by setting resourceLocation or providing the the constructor as well). * You may end up with something like /my/leading/path/en-US/my/trailing/path/utterances.yml * where "en-US" is the only portion you cannot influence as it comes with the locale of * a speechlet request. */ public ResourceUtteranceReader() { this(DEFAULT_LEADING_PATH, DEFAULT_RESOURCE_LOCATION); } /** * New reader for classloader-resources giving it a valid leading path. Note that a * fully qualified path is a concatenation of the leading path (set in the constructor), * the locale (given to the read-method) and the trailing resource location containing the actual filename (can be overridden * by setting resourceLocation or providing the the constructor as well). * You may end up with something like /my/leading/path/en-US/my/trailing/path/utterances.yml * where "en-US" is the only portion you cannot influence as it comes with the locale of * a speechlet request. * @param leadingPath leading path to the actual resource (YAML) file */ public ResourceUtteranceReader(final String leadingPath) { this(leadingPath, DEFAULT_RESOURCE_LOCATION); } /** * New reader for classloader-resources giving it a valid leading path. Note that a * fully qualified path is a concatenation of the leading path (set in the constructor), * the locale (given to the read-method) and the trailing resource location containing the actual filename (can be overridden * by setting resourceLocation or providing the the constructor as well). * You may end up with something like /my/leading/path/en-US/my/trailing/path/utterances.yml * where "en-US" is the only portion you cannot influence as it comes with the locale of * a speechlet request. * @param leadingPath leading path to the actual resource (YAML) file * @param resourceLocation the resource location. must end with ".yml" */ public ResourceUtteranceReader(final String leadingPath, final String resourceLocation) { setResourceLocation(resourceLocation); final StringBuilder sb = new StringBuilder(); sb.append(leadingPath.startsWith("/") ? leadingPath.substring(1) : leadingPath); if (!leadingPath.endsWith("/")) sb.append("/"); this.leadingPath = sb.toString(); } /** * {@inheritDoc} */ @Override public String getLeadingPath() { return leadingPath; } /** * {@inheritDoc} */ @Override public String getResourceLocation() { return this.resourceLocation; } /** * {@inheritDoc} */ @Override public void setResourceLocation(final String resourceLocation) { Validate.notBlank(resourceLocation, "No resource location is set to read from."); Validate.notBlank(resourceLocation.replace("/", ""), "No resource location is set to read from."); Validate.isTrue(resourceLocation.endsWith(".yml"), "Resource location must end with .yml"); this.resourceLocation = resourceLocation.startsWith("/") ? resourceLocation : "/" + resourceLocation; } /** * {@inheritDoc} */ @Override public ResourceUtteranceReader fromResourceLocation(final String resourceLocation) { setResourceLocation(resourceLocation); return this; } /** * {@inheritDoc} */ @Override public InputStream read(final String locale) { Validate.notNull(locale, "Locale must not be blank."); final String resourcePath = leadingPath + locale + resourceLocation; final String resourcePath2 = resourcePath.startsWith("/") ? resourcePath.substring(1) : resourcePath; final ClassLoader cl = getClass().getClassLoader(); Validate.notNull(cl.getResource(resourcePath2), "Resource " + resourcePath2 + " does not exist in current context."); return cl.getResourceAsStream(resourcePath2); } }