/****************************************************************************** * * Copyright 2014 Paphus Solutions Inc. * * Licensed under the Eclipse Public License, Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.botlibre.sdk; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.StringReader; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.ByteArrayBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.botlibre.sdk.config.AvatarConfig; import org.botlibre.sdk.config.AvatarMedia; import org.botlibre.sdk.config.AvatarMessage; import org.botlibre.sdk.config.BotModeConfig; import org.botlibre.sdk.config.BrowseConfig; import org.botlibre.sdk.config.ChannelConfig; import org.botlibre.sdk.config.ChatConfig; import org.botlibre.sdk.config.ChatResponse; import org.botlibre.sdk.config.Config; import org.botlibre.sdk.config.ContentConfig; import org.botlibre.sdk.config.ConversationConfig; import org.botlibre.sdk.config.DomainConfig; import org.botlibre.sdk.config.ForumConfig; import org.botlibre.sdk.config.ForumPostConfig; import org.botlibre.sdk.config.InstanceConfig; import org.botlibre.sdk.config.LearningConfig; import org.botlibre.sdk.config.MediaConfig; import org.botlibre.sdk.config.ResponseConfig; import org.botlibre.sdk.config.ResponseSearchConfig; import org.botlibre.sdk.config.ScriptConfig; import org.botlibre.sdk.config.ScriptSourceConfig; import org.botlibre.sdk.config.Speech; import org.botlibre.sdk.config.TrainingConfig; import org.botlibre.sdk.config.UserAdminConfig; import org.botlibre.sdk.config.UserConfig; import org.botlibre.sdk.config.UserMessageConfig; import org.botlibre.sdk.config.VoiceConfig; import org.botlibre.sdk.config.WebMediumConfig; /** * Connection class for a REST service connection. * The SDK connection gives you access to the paphus or libre server services using a REST API. * <p> * The services include: * <ul> * <li> User management (account creation, validation) * <li> Bot access, chat, and administration * <li> Forum access, posting, and administration * <li> Live chat access, chat, and administration * <li> Domain access, and administration * </ul> */ public class SDKConnection { protected static String[] types = new String[]{"Bots", "Forums", "Live Chat", "Domains", "Scripts"}; protected static String[] channelTypes = new String[]{"ChatRoom", "OneOnOne"}; protected static String[] accessModes = new String[]{"Everyone", "Users", "Members", "Administrators"}; protected static String[] mediaAccessModes = new String[]{"Everyone", "Users", "Members", "Administrators", "Disabled"}; protected static String[] learningModes = new String[]{"Disabled", "Administrators", "Users", "Everyone"}; protected static String[] correctionModes = new String[]{"Disabled", "Administrators", "Users", "Everyone"}; protected static String[] botModes = new String[]{"ListenOnly", "AnswerOnly", "AnswerAndListen"}; protected String url; protected UserConfig user; protected DomainConfig domain; protected Credentials credentials; protected boolean debug = false; protected SDKException exception; /** * Return the name of the default user image. */ public static String defaultUserImage() { return "images/user-thumb.jpg"; } /** * Create an SDK connection. */ public SDKConnection() { } /** * Create an SDK connection with the credentials. * Use the Credentials subclass specific to your server. */ public SDKConnection(Credentials credentials) { this.credentials = credentials; this.url = credentials.url; } /** * Validate the user credentials (password, or token). * The user details are returned (with a connection token, password removed). * The user credentials are soted in the connection, and used on subsequent calls. * An SDKException is thrown if the connect failed. */ public UserConfig connect(UserConfig config) { config.addCredentials(this); String xml = POST(this.url + "/check-user", config.toXML()); Element root = parse(xml); if (root == null) { this.user = null; return null; } try { UserConfig user = new UserConfig(); user.parseXML(root); this.user = user; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } return this.user; } /** * Execute the custom API. */ public Config custom(String api, Config config, Config result) { config.addCredentials(this); String xml = POST(this.url + "/" + api, config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { result.parseXML(root); } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } return result; } /** * Connect to the live chat channel and return a LiveChatConnection. * A LiveChatConnection is separate from an SDKConnection and uses web sockets for * asynchronous communication. * The listener will be notified of all messages. */ public LiveChatConnection openLiveChat(ChannelConfig channel, LiveChatListener listener) { LiveChatConnection connection = new LiveChatConnection(this.credentials, listener); connection.connect(channel, this.user); return connection; } /** * Connect to the domain. * A domain is an isolated content space. * Any browse or query request will be specific to the domain's content. */ public DomainConfig connect(DomainConfig config) { this.domain = fetch(config); return this.domain; } /** * Disconnect from the connection. * An SDKConnection does not keep a live connection, but this resets its connected user and domain. */ public void disconnect() { this.user = null; this.domain = null; } /** * Fetch the user details. */ public UserConfig fetch(UserConfig config) { config.addCredentials(this); String xml = POST(this.url + "/view-user", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { UserConfig user = new UserConfig(); user.parseXML(root); return user; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Fetch the URL for the image from the server. */ public URL fetchImage(String image) { try { return new URL("http://" + this.credentials.host + this.credentials.app + "/" + image); } catch (Exception exception) { this.exception = new SDKException(exception); throw this.exception; } } /** * Fetch the forum post details for the forum post id. */ public ForumPostConfig fetch(ForumPostConfig config) { config.addCredentials(this); String xml = POST(this.url + "/check-forum-post", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { ForumPostConfig post = new ForumPostConfig(); post.parseXML(root); return post; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Create a new user. */ public UserConfig create(UserConfig config) { config.addCredentials(this); String xml = POST(this.url + "/create-user", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { UserConfig user = new UserConfig(); user.parseXML(root); this.user = user; return user; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Create a new forum post. * You must set the forum id for the post. */ public ForumPostConfig create(ForumPostConfig config) { config.addCredentials(this); String xml = POST(this.url + "/create-forum-post", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { ForumPostConfig post = new ForumPostConfig(); post.parseXML(root); return post; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Create a new file/image/media attachment for a chat channel. */ public MediaConfig createChannelFileAttachment(String file, MediaConfig config) { config.addCredentials(this); String xml = POSTFILE(this.url + "/create-channel-attachment", file, config.name, config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { MediaConfig media = new MediaConfig(); media.parseXML(root); return media; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Create a reply to a forum post. * You must set the parent id for the post replying to. */ public ForumPostConfig createReply(ForumPostConfig config) { config.addCredentials(this); String xml = POST(this.url + "/create-reply", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { ForumPostConfig reply = new ForumPostConfig(); reply.parseXML(root); return reply; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Create a user message. * This can be used to send a user a direct message. * SPAM will cause your account to be deleted. */ public void createUserMessage(UserMessageConfig config) { config.addCredentials(this); POST(this.url + "/create-user-message", config.toXML()); } /** * Fetch the content details from the server. * The id or name and domain of the object must be set. */ @SuppressWarnings("unchecked") public <T extends WebMediumConfig> T fetch(T config) { config.addCredentials(this); String xml = POST(this.url + "/check-" + config.getType(), config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { config = (T)config.getClass().newInstance(); config.parseXML(root); return config; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Create the new content. * The content will be returned with its new id. */ @SuppressWarnings("unchecked") public <T extends WebMediumConfig> T create(T config) { config.addCredentials(this); String xml = POST(this.url + "/create-" + config.getType(), config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { config = (T)config.getClass().newInstance(); config.parseXML(root); return config; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Update the content. */ @SuppressWarnings("unchecked") public <T extends WebMediumConfig> T update(T config) { config.addCredentials(this); String xml = POST(this.url + "/update-" + config.getType(), config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { config = (T)config.getClass().newInstance(); config.parseXML(root); return config; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Update the forum post. */ public ForumPostConfig update(ForumPostConfig config) { config.addCredentials(this); String xml = POST(this.url + "/update-forum-post", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { config = new ForumPostConfig(); config.parseXML(root); return config; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Create or update the response. * This can also be used to flag, unflag, validate, or invalidate a response. */ public ResponseConfig saveResponse(ResponseConfig config) { config.addCredentials(this); String xml = POST(this.url + "/save-response", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { ResponseConfig response = new ResponseConfig(); response.parseXML(root); return response; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Update the user details. * The password must be passed to allow the update. */ public UserConfig update(UserConfig config) { config.addCredentials(this); String xml = POST(this.url + "/update-user", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { UserConfig user = new UserConfig(); user.parseXML(root); this.user = user; return user; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Permanently delete the content with the id. */ public void delete(WebMediumConfig config) { config.addCredentials(this); POST(this.url + "/delete-" + config.getType(), config.toXML()); } /** * Permanently delete the forum post with the id. */ public void delete(ForumPostConfig config) { config.addCredentials(this); POST(this.url + "/delete-forum-post", config.toXML()); } /** * Permanently delete the response, greetings, or default response with the response id (and question id). */ public void delete(ResponseConfig config) { config.addCredentials(this); POST(this.url + "/delete-response", config.toXML()); } /** * Permanently delete the avatar media. */ public void delete(AvatarMedia config) { config.addCredentials(this); POST(this.url + "/delete-avatar-media", config.toXML()); } /** * Permanently delete the avatar background. */ public void deleteAvatarBackground(AvatarConfig config) { config.addCredentials(this); POST(this.url + "/delete-avatar-background", config.toXML()); } /** * Save the avatar media tags. */ public void saveAvatarMedia(AvatarMedia config) { config.addCredentials(this); POST(this.url + "/save-avatar-media", config.toXML()); } /** * Flag the content as offensive, a reason is required. */ public void flag(WebMediumConfig config) { config.addCredentials(this); POST(this.url + "/flag-" + config.getType(), config.toXML()); } /** * Subscribe for email updates for the post. */ public void subscribe(ForumPostConfig config) { config.addCredentials(this); POST(this.url + "/subscribe-post", config.toXML()); } /** * Subscribe for email updates for the forum. */ public void subscribe(ForumConfig config) { config.addCredentials(this); POST(this.url + "/subscribe-forum", config.toXML()); } /** * Unsubscribe from email updates for the post. */ public void unsubscribe(ForumPostConfig config) { config.addCredentials(this); POST(this.url + "/unsubscribe-post", config.toXML()); } /** * Unsubscribe from email updates for the forum. */ public void unsubscribe(ForumConfig config) { config.addCredentials(this); POST(this.url + "/unsubscribe-forum", config.toXML()); } /** * Thumbs up the content. */ public void thumbsUp(WebMediumConfig config) { config.addCredentials(this); POST(this.url + "/thumbs-up-" + config.getType(), config.toXML()); } /** * Thumbs down the content. */ public void thumbsDown(WebMediumConfig config) { config.addCredentials(this); POST(this.url + "/thumbs-down-" + config.getType(), config.toXML()); } /** * Rate the content. */ public void star(WebMediumConfig config) { config.addCredentials(this); POST(this.url + "/star-" + config.getType(), config.toXML()); } /** * Thumbs up the content. */ public void thumbsUp(ForumPostConfig config) { config.addCredentials(this); POST(this.url + "/thumbs-up-post", config.toXML()); } /** * Thumbs down the content. */ public void thumbsDown(ForumPostConfig config) { config.addCredentials(this); POST(this.url + "/thumbs-down-post", config.toXML()); } /** * Rate the content. */ public void star(ForumPostConfig config) { config.addCredentials(this); POST(this.url + "/star-post", config.toXML()); } /** * Flag the forum post as offensive, a reason is required. */ public void flag(ForumPostConfig config) { config.addCredentials(this); POST(this.url + "/flag-forum-post", config.toXML()); } /** * Flag the user post as offensive, a reason is required. */ public void flag(UserConfig config) { config.addCredentials(this); POST(this.url + "/flag-user", config.toXML()); } /** * Process the bot chat message and return the bot's response. * The ChatConfig should contain the conversation id if part of a conversation. * If a new conversation the conversation id is returned in the response. */ public ChatResponse chat(ChatConfig config) { config.addCredentials(this); String xml = POST(this.url + "/post-chat", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { ChatResponse response = new ChatResponse(); response.parseXML(root); return response; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Process the avatar message and return the avatars response. * This allows the speech and video animation for an avatar to be generated for the message. */ public ChatResponse avatarMessage(AvatarMessage config) { config.addCredentials(this); String xml = POST(this.url + "/avatar-message", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { ChatResponse response = new ChatResponse(); response.parseXML(root); return response; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Process the speech message and return the server generate text-to-speech audio file. * This allows for server-side speech generation. */ public String tts(Speech config) { config.addCredentials(this); return POST(this.url + "/speak", config.toXML()); } /** * Return the administrators of the content. */ public List<String> getAdmins(WebMediumConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-" + config.getType() + "-admins", config.toXML()); List<String> users = new ArrayList<String>(); Element root = parse(xml); if (root == null) { return users; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { UserConfig user = new UserConfig(); user.parseXML((Element)root.getChildNodes().item(index)); users.add(user.user); } return users; } /** * Return the list of user details for the comma separated values list of user ids. */ public List<UserConfig> getUsers(String usersCSV) { UserConfig config = new UserConfig(); config.user = usersCSV; config.addCredentials(this); String xml = POST(this.url + "/get-users", config.toXML()); List<UserConfig> users = new ArrayList<UserConfig>(); Element root = parse(xml); if (root == null) { return users; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { Element child = (Element)root.getChildNodes().item(index); UserConfig userConfig = new UserConfig(); userConfig.parseXML(child); users.add(userConfig); } return users; } /** * Return the list of forum posts for the forum browse criteria. */ public List<ForumPostConfig> getPosts(BrowseConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-forum-posts", config.toXML()); List<ForumPostConfig> instances = new ArrayList<ForumPostConfig>(); Element root = parse(xml); if (root == null) { return instances; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { ForumPostConfig post = new ForumPostConfig(); post.parseXML((Element)root.getChildNodes().item(index)); instances.add(post); } return instances; } /** * Return the list of categories for the type, and domain. */ public List<ContentConfig> getCategories(ContentConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-categories", config.toXML()); List<ContentConfig> categories = new ArrayList<ContentConfig>(); Element root = parse(xml); if (root == null) { return categories; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { ContentConfig category = new ContentConfig(); category.parseXML((Element)root.getChildNodes().item(index)); categories.add(category); } return categories; } /** * Return the list of tags for the type, and domain. */ public List<String> getTags(ContentConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-tags", config.toXML()); List<String> tags = new ArrayList<String>(); tags.add(""); Element root = parse(xml); if (root == null) { return tags; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { tags.add(((Element)root.getChildNodes().item(index)).getAttribute("name")); } return tags; } /** * Return the list of bot templates. */ public List<String> getTemplates() { String xml = GET(this.url + "/get-all-templates"); List<String> instances = new ArrayList<String>(); Element root = parse(xml); if (root == null) { return instances; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { instances.add(((Element)root.getChildNodes().item(index)).getAttribute("name")); } return instances; } /** * Return the users for the content. */ public List<String> getUsers(WebMediumConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-" + config.getType() + "-users", config.toXML()); List<String> users = new ArrayList<String>(); Element root = parse(xml); if (root == null) { return users; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { UserConfig user = new UserConfig(); user.parseXML((Element)root.getChildNodes().item(index)); users.add(user.user); } return users; } /** * Return the channel's bot configuration. */ public BotModeConfig getChannelBotMode(ChannelConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-channel-bot-mode", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { BotModeConfig botMode = new BotModeConfig(); botMode.parseXML(root); return botMode; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Save the channel's bot configuration. */ public void saveChannelBotMode(BotModeConfig config) { config.addCredentials(this); POST(this.url + "/save-channel-bot-mode", config.toXML()); } /** * Save the forum's bot configuration. */ public void saveForumBotMode(BotModeConfig config) { config.addCredentials(this); POST(this.url + "/save-forum-bot-mode", config.toXML()); } /** * Save the bot's learning configuration. */ public void saveLearning(LearningConfig config) { config.addCredentials(this); POST(this.url + "/save-learning", config.toXML()); } /** * Save the bot's voice configuration. */ public void saveVoice(VoiceConfig config) { config.addCredentials(this); POST(this.url + "/save-voice", config.toXML()); } /** * Save the bot's avatar configuration. */ public void saveBotAvatar(InstanceConfig config) { config.addCredentials(this); POST(this.url + "/save-bot-avatar", config.toXML()); } /** * Train the bot with a new question/response pair. */ public void train(TrainingConfig config) { config.addCredentials(this); POST(this.url + "/train-instance", config.toXML()); } /** * Perform the user administration task (add or remove users, or administrators). */ public void userAdmin(UserAdminConfig config) { config.addCredentials(this); POST(this.url + "/user-admin", config.toXML()); } /** * Add the avatar media file to the avatar. */ public void createAvatarMedia(String file, AvatarMedia config) { config.addCredentials(this); POSTFILE(this.url + "/create-avatar-media", file, config.name, config.toXML()); } public String POSTFILE(String url, String path, String name, String xml) { if (this.debug) { System.out.println("POST: " + url); System.out.println("file: " + path); System.out.println("XML: " + xml); } String result = ""; try { File file = new File(path); FileInputStream stream = new FileInputStream(file); ByteArrayOutputStream output = new ByteArrayOutputStream(); int read = 0; byte[] buffer = new byte[4096]; while ((read = stream.read(buffer)) != -1 ) { output.write(buffer, 0, read); } byte[] byte_arr = output.toByteArray(); stream.close(); ByteArrayBody fileBody = new ByteArrayBody(byte_arr, name); MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); multipartEntity.addPart("file", fileBody); multipartEntity.addPart("xml", new StringBody(xml)); HttpClient httpclient = new DefaultHttpClient(); HttpResponse response = null; HttpPost httppost = new HttpPost(url); httppost.setEntity(multipartEntity); response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); if (entity != null) { result = EntityUtils.toString(entity, HTTP.UTF_8); } if ((response.getStatusLine().getStatusCode() != 200) && (response.getStatusLine().getStatusCode() != 204)) { this.exception = new SDKException("" + response.getStatusLine().getStatusCode() + " : " + result); throw this.exception; } } catch (Exception exception) { this.exception = new SDKException(exception); throw this.exception; } return result; } /** * Return the forum's bot configuration. */ public BotModeConfig getForumBotMode(ForumConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-forum-bot-mode", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { BotModeConfig botMode = new BotModeConfig(); botMode.parseXML(root); return botMode; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Return the bot's voice configuration. */ public VoiceConfig getVoice(InstanceConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-voice", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { VoiceConfig voice = new VoiceConfig(); voice.parseXML(root); return voice; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Return the bot's default responses. */ public List<String> getDefaultResponses(InstanceConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-default-responses", config.toXML()); List<String> defaultResponses = new ArrayList<String>(); Element root = parse(xml); if (root == null) { return defaultResponses; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { defaultResponses.add(((Element)root.getChildNodes().item(index)).getChildNodes().item(0).getTextContent()); } return defaultResponses; } /** * Return the bot's greetings. */ public List<String> getGreetings(InstanceConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-greetings", config.toXML()); List<String> greetings = new ArrayList<String>(); Element root = parse(xml); if (root == null) { return greetings; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { greetings.add(((Element)root.getChildNodes().item(index)).getChildNodes().item(0).getTextContent()); } return greetings; } /** * Search the bot's responses. */ public List<ResponseConfig> getResponses(ResponseSearchConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-responses", config.toXML()); List<ResponseConfig> responses = new ArrayList<ResponseConfig>(); Element root = parse(xml); if (root == null) { return responses; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { ResponseConfig response = new ResponseConfig(); response.parseXML((Element)root.getChildNodes().item(index)); responses.add(response); } return responses; } /** * Search the bot's conversations. */ public List<ConversationConfig> getConversations(ResponseSearchConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-conversations", config.toXML()); List<ConversationConfig> conversations = new ArrayList<ConversationConfig>(); Element root = parse(xml); if (root == null) { return conversations; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { ConversationConfig response = new ConversationConfig(); response.parseXML((Element)root.getChildNodes().item(index)); conversations.add(response); } return conversations; } /** * Return the bot's learning configuration. */ public LearningConfig getLearning(InstanceConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-learning", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { LearningConfig learning = new LearningConfig(); learning.parseXML(root); return learning; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Return the list of content for the browse criteria. * The type defines the content type (one of Bot, Forum, Channel, Domain). */ public List<WebMediumConfig> browse(BrowseConfig config) { config.addCredentials(this); String type = ""; if (config.type.equals("Bot")) { type = "/get-instances"; } else { type = "/get-" + config.type.toLowerCase() + "s"; } String xml = POST(this.url + type, config.toXML()); List<WebMediumConfig> instances = new ArrayList<WebMediumConfig>(); Element root = parse(xml); if (root == null) { return instances; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { WebMediumConfig instance = null; if (config.type.equals("Bot")) { instance = new InstanceConfig(); } else if (config.type.equals("Forum")) { instance = new ForumConfig(); } else if (config.type.equals("Channel")) { instance = new ChannelConfig(); } else if (config.type.equals("Domain")) { instance = new DomainConfig(); } else if (config.type.equals("Avatar")) { instance = new AvatarConfig(); } else if (config.type.equals("Script")) { instance = new ScriptConfig(); } instance.parseXML((Element)root.getChildNodes().item(index)); instances.add(instance); } return instances; } /** * Return the list of media for the avatar. */ public List<AvatarMedia> getAvatarMedia(AvatarConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-avatar-media", config.toXML()); List<AvatarMedia> instances = new ArrayList<AvatarMedia>(); Element root = parse(xml); if (root == null) { return instances; } for (int index = 0; index < root.getChildNodes().getLength(); index++) { AvatarMedia instance = new AvatarMedia(); instance.parseXML((Element)root.getChildNodes().item(index)); instances.add(instance); } return instances; } /** * Return the script source */ public ScriptSourceConfig getScriptSource(ScriptConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-script-source", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { ScriptSourceConfig script = new ScriptSourceConfig(); script.parseXML(root); return script; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Create or update script - Save the script source */ public void saveScriptSource(ScriptSourceConfig config) { config.addCredentials(this); POST(this.url + "/save-script-source", config.toXML()); } /** * Return the source code for a single bot script */ public ScriptSourceConfig getBotScriptSource(ScriptSourceConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-bot-script-source", config.toXML()); Element root = parse(xml); if (root == null) { return null; } try { ScriptSourceConfig botScript = new ScriptSourceConfig(); botScript.parseXML(root); return botScript; } catch (Exception exception) { this.exception = SDKException.parseFailure(exception); throw this.exception; } } /** * Return a list of the bots scripts */ public List<ScriptConfig> getBotScripts(InstanceConfig config) { config.addCredentials(this); String xml = POST(this.url + "/get-bot-scripts", config.toXML()); List<ScriptConfig> botScripts = new ArrayList<ScriptConfig>(); Element root = parse(xml); if (root == null) { return botScripts; } for (int i = 0; i < root.getChildNodes().getLength(); i++) { ScriptConfig script = new ScriptConfig(); script.parseXML((Element)root.getChildNodes().item(i)); botScripts.add(script); } return botScripts; } /** * import a script to the bot */ public void importBotScript(ScriptConfig config) { config.addCredentials(this); POST(this.url + "/import-bot-script", config.toXML()); } /** * import a chatlog/response list to the bot */ public void importBotLog(ScriptConfig config) { config.addCredentials(this); POST(this.url + "/import-bot-log", config.toXML()); } /** * Save the bot script source */ public void saveBotScriptSource(ScriptSourceConfig config) { config.addCredentials(this); POST(this.url + "/save-bot-script-source", config.toXML()); } /** * Delete selected bot script */ public void deleteBotScript(ScriptSourceConfig config) { config.addCredentials(this); POST(this.url + "/delete-bot-script", config.toXML()); } /** * Move up one bot script */ public void upBotScript(ScriptSourceConfig config) { config.addCredentials(this); POST(this.url + "/up-bot-script", config.toXML()); } /** * Move down one bot script */ public void downBotScript(ScriptSourceConfig config) { config.addCredentials(this); POST(this.url + "/down-bot-script", config.toXML()); } /** * Return the list of content types. */ public String[] getTypes() { return types; } /** * Return the channel types. */ public String[] getChannelTypes() { return channelTypes; } /** * Return the access mode types. */ public String[] getAccessModes() { return accessModes; } /** * Return the media access mode types. */ public String[] getMediaAccessModes() { return mediaAccessModes; } /** * Return the learning mode types. */ public String[] getLearningModes() { return learningModes; } /** * Return the correction mode types. */ public String[] getCorrectionModes() { return correctionModes; } /** * Return the bot mode types. */ public String[] getBotModes() { return botModes; } /** * Return the current connected user. */ public UserConfig getUser() { return user; } /** * Set the current connected user. * connect() should be used to validate and connect a user. */ public void setUser(UserConfig user) { this.user = user; } /** * Return the current domain. * A domain is an isolated content space. */ public DomainConfig getDomain() { return domain; } /** * Set the current domain. * A domain is an isolated content space. * connect() should be used to validate and connect a domain. */ public void setDomain(DomainConfig domain) { this.domain = domain; } /** * Return the current application credentials. */ public Credentials getCredentials() { return credentials; } /** * Set the application credentials. */ public void setCredentials(Credentials credentials) { this.credentials = credentials; this.url = credentials.url; } /** * Return is debugging has been enabled. */ public boolean isDebug() { return debug; } /** * Enable debugging, debug messages will be logged to System.out. */ public void setDebug(boolean debug) { this.debug = debug; } /** * Return the last thrown exception. */ public SDKException getException() { return exception; } protected void setException(SDKException exception) { this.exception = exception; } public String GET(String url) { if (this.debug) { System.out.println("GET: " + url); } String xml = null; try { HttpClient httpClient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); HttpGet httpGet = new HttpGet(url); HttpResponse response = httpClient.execute(httpGet, localContext); HttpEntity entity = response.getEntity(); xml = EntityUtils.toString(entity, HTTP.UTF_8); if (response.getStatusLine().getStatusCode() != 200) { this.exception = new SDKException("" + response.getStatusLine().getStatusCode() + " : " + xml); return ""; } } catch (Exception exception) { if (this.debug) { exception.printStackTrace(); } this.exception = new SDKException(exception); throw this.exception; } return xml; } public String POST(String url, String xml) { if (this.debug) { System.out.println("POST: " + url); System.out.println("XML: " + xml); } String result = ""; try { HttpClient httpClient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); HttpPost httpPost = new HttpPost(url); StringEntity content = new StringEntity(xml, "utf-8"); content.setContentType("application/xml"); httpPost.setEntity(content); HttpResponse response = httpClient.execute(httpPost, localContext); HttpEntity entity = response.getEntity(); if (entity != null) { result = EntityUtils.toString(entity, HTTP.UTF_8); } if ((response.getStatusLine().getStatusCode() != 200) && (response.getStatusLine().getStatusCode() != 204)) { this.exception = new SDKException("" + response.getStatusLine().getStatusCode() + " : " + result); throw this.exception; } } catch (Exception exception) { if (this.debug) { exception.printStackTrace(); } this.exception = new SDKException(exception); throw this.exception; } return result; } public Element parse(String xml) { if (this.debug) { System.out.println(xml); } Document dom = null; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = factory.newDocumentBuilder(); InputSource source = new InputSource(); source.setCharacterStream(new StringReader(xml)); dom = builder.parse(source); return dom.getDocumentElement(); } catch (Exception exception) { if (this.debug) { exception.printStackTrace(); } this.exception = new SDKException(exception.getMessage(), exception); throw this.exception; } } }