├── .bettercodehub.yml ├── .github ├── scripts │ ├── build_xatkit.sh │ └── decrypt_ci_cd_secrets.sh └── workflows │ └── maven.yml ├── .gitignore ├── .util ├── build_xatkit.sh ├── publish_javadoc.sh ├── report_updates.sh └── update_eclipse_dropins.sh ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── codecov.yml ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── xatkit │ │ ├── core │ │ ├── EventDefinitionRegistry.java │ │ ├── ExecutionService.java │ │ ├── XatkitBot.java │ │ ├── XatkitException.java │ │ ├── platform │ │ │ ├── RuntimePlatform.java │ │ │ ├── action │ │ │ │ ├── RuntimeAction.java │ │ │ │ ├── RuntimeActionResult.java │ │ │ │ ├── RuntimeArtifactAction.java │ │ │ │ └── RuntimeMessageAction.java │ │ │ └── io │ │ │ │ ├── IntentRecognitionHelper.java │ │ │ │ ├── JsonEventMatcher.java │ │ │ │ ├── RuntimeEventProvider.java │ │ │ │ └── WebhookEventProvider.java │ │ ├── recognition │ │ │ ├── AbstractIntentRecognitionProvider.java │ │ │ ├── DefaultFallbackIntent.java │ │ │ ├── EntityMapper.java │ │ │ ├── IntentRecognitionProvider.java │ │ │ ├── IntentRecognitionProviderException.java │ │ │ ├── IntentRecognitionProviderFactory.java │ │ │ ├── IntentRecognitionProviderFactoryConfiguration.java │ │ │ ├── RecognitionMonitor.java │ │ │ ├── processor │ │ │ │ ├── InputPreProcessor.java │ │ │ │ └── IntentPostProcessor.java │ │ │ └── regex │ │ │ │ ├── RegExEntityMapper.java │ │ │ │ └── RegExIntentRecognitionProvider.java │ │ └── server │ │ │ ├── ContentHttpHandler.java │ │ │ ├── EmptyContentRestHandler.java │ │ │ ├── HttpEntityHelper.java │ │ │ ├── HttpHandler.java │ │ │ ├── HttpMethod.java │ │ │ ├── HttpUtils.java │ │ │ ├── JsonRestHandler.java │ │ │ ├── RestHandler.java │ │ │ ├── RestHandlerException.java │ │ │ ├── RestHandlerFactory.java │ │ │ ├── XatkitServer.java │ │ │ └── XatkitServerUtils.java │ │ ├── dsl │ │ ├── DSL.java │ │ ├── entity │ │ │ ├── CompositeEntryFragmentStep.java │ │ │ ├── CompositeEntryStep.java │ │ │ ├── CustomEntityDefinitionProvider.java │ │ │ ├── EntityDefinitionReferenceProvider.java │ │ │ ├── MappingEntryStep.java │ │ │ ├── MappingReferenceValueStep.java │ │ │ ├── MappingSynonymStep.java │ │ │ └── impl │ │ │ │ ├── CompositeEntityDefinitionBuilder.java │ │ │ │ ├── CompositeEntityDefinitionEntryBuilder.java │ │ │ │ ├── CustomEntityDefinitionProviderImpl.java │ │ │ │ ├── MappingEntityDefinitionBuilder.java │ │ │ │ └── MappingEntityDefinitionEntryBuilder.java │ │ ├── intent │ │ │ ├── EventContextParameterStep.java │ │ │ ├── EventDefinitionProvider.java │ │ │ ├── IntentContextLifespanStep.java │ │ │ ├── IntentContextParameterEntityStep.java │ │ │ ├── IntentContextParameterFragmentStep.java │ │ │ ├── IntentContextParameterStep.java │ │ │ ├── IntentDefinitionProvider.java │ │ │ ├── IntentMandatoryTrainingSentenceStep.java │ │ │ ├── IntentOptionalTrainingSentenceStep.java │ │ │ ├── IntentVar.java │ │ │ └── impl │ │ │ │ ├── EventDefinitionBuilder.java │ │ │ │ ├── EventDefinitionProviderImpl.java │ │ │ │ ├── IntentContextParameterBuilder.java │ │ │ │ ├── IntentDefinitionBuilder.java │ │ │ │ └── IntentDefinitionProviderImpl.java │ │ ├── library │ │ │ ├── EntityStep.java │ │ │ ├── IntentStep.java │ │ │ ├── LibraryProvider.java │ │ │ └── impl │ │ │ │ ├── LibraryBuilder.java │ │ │ │ └── LibraryProviderImpl.java │ │ ├── model │ │ │ ├── DefaultFallbackStateStep.java │ │ │ ├── ExecutionModelProvider.java │ │ │ ├── InitStateStep.java │ │ │ ├── ListenToStep.java │ │ │ ├── StateStep.java │ │ │ ├── UseEventStep.java │ │ │ ├── UsePlatformStep.java │ │ │ └── impl │ │ │ │ ├── ExecutionModelBuilder.java │ │ │ │ └── ExecutionModelProviderImpl.java │ │ └── state │ │ │ ├── BodyStep.java │ │ │ ├── EventPredicateStep.java │ │ │ ├── FallbackBodyStep.java │ │ │ ├── FallbackStep.java │ │ │ ├── MoveToStep.java │ │ │ ├── NameStep.java │ │ │ ├── NextStep.java │ │ │ ├── OptionalWhenStep.java │ │ │ ├── StateProvider.java │ │ │ ├── StateVar.java │ │ │ ├── TransitionStep.java │ │ │ ├── WhenStep.java │ │ │ └── impl │ │ │ ├── StateBuilder.java │ │ │ ├── StateProviderImpl.java │ │ │ └── TransitionBuilder.java │ │ ├── i18n │ │ └── XatkitI18nHelper.java │ │ ├── library │ │ └── core │ │ │ └── CoreLibrary.java │ │ ├── platform │ │ └── core │ │ │ ├── CorePlatform.java │ │ │ ├── CoreUtils.java │ │ │ └── io │ │ │ └── CronEventProvider.java │ │ └── util │ │ ├── EMFUtils.java │ │ ├── FileUtils.java │ │ ├── IntentUtils.java │ │ ├── Loader.java │ │ └── XatkitEnvironmentConfiguration.java ├── javadoc │ └── com │ │ └── xatkit │ │ ├── core │ │ ├── interpreter │ │ │ ├── operation │ │ │ │ ├── object │ │ │ │ │ └── package-info.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── platform │ │ │ ├── action │ │ │ │ └── package-info.java │ │ │ ├── io │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ ├── recognition │ │ │ ├── dialogflow │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ ├── server │ │ │ └── package-info.java │ │ └── session │ │ │ └── package-info.java │ │ └── util │ │ └── package-info.java └── resources │ ├── log4j2.xml │ └── xatkit_checks.xml └── test ├── java └── com │ └── xatkit │ ├── AbstractActionTest.java │ ├── AbstractEventProviderTest.java │ ├── AbstractPlatformTest.java │ ├── AbstractXatkitTest.java │ ├── core │ ├── ExecutionServiceTest.java │ ├── XatkitBotTest.java │ ├── platform │ │ ├── RuntimePlatformTest.java │ │ ├── action │ │ │ ├── RuntimeActionResultTest.java │ │ │ └── RuntimeMessageActionTest.java │ │ └── io │ │ │ └── JsonEventMatcherTest.java │ ├── recognition │ │ ├── AbstractIntentRecognitionProviderTest.java │ │ ├── EntityMapperTest.java │ │ ├── IntentRecognitionProviderFactoryTest.java │ │ ├── IntentRecognitionProviderTest.java │ │ ├── processor │ │ │ ├── PostProcessorNoConfiguration.java │ │ │ ├── PostProcessorWithConfiguration.java │ │ │ └── PreProcessorNoConfiguration.java │ │ └── regex │ │ │ └── RegExIntentRecognitionProviderTest.java │ ├── server │ │ ├── HttpHandlerTest.java │ │ ├── HttpUtilsTest.java │ │ └── XatkitServerTest.java │ ├── session │ │ └── StateContextTest.java │ └── util │ │ ├── LoaderTest.java │ │ └── stubs │ │ ├── ExceptionClass.java │ │ └── LoadableClass.java │ ├── dsl │ ├── EntityTest.java │ ├── EventTest.java │ ├── ExecutionModelTest.java │ ├── IntentTest.java │ ├── LibraryTest.java │ └── StateTest.java │ ├── platform │ └── core │ │ └── io │ │ └── CronEventProviderTest.java │ ├── stubs │ ├── EmptyRuntimePlatform.java │ ├── StubRuntimePlatform.java │ ├── StubXatkitServer.java │ ├── TestingStateContext.java │ ├── TestingStateContextFactory.java │ └── action │ │ ├── ErroringStubRuntimeAction.java │ │ ├── StubRuntimeAction.java │ │ ├── StubRuntimeActionNoParameter.java │ │ ├── StubRuntimeActionTwoConstructors.java │ │ ├── StubRuntimeMessageAction.java │ │ ├── StubRuntimeMessageActionIOException.java │ │ └── StubRuntimeMessageActionIOExceptionThenOk.java │ └── test │ ├── bot │ ├── IntentProviderTestBot.java │ └── TestBot.java │ └── util │ └── VariableLoaderHelper.java └── resources ├── empty-configuration.properties ├── log4j2-test.xml ├── test-variables-empty.properties └── xatkit-secrets.zip.gpg /.bettercodehub.yml: -------------------------------------------------------------------------------- 1 | exclude: 2 | - /.util/.* 3 | - /core_resources/.* 4 | - /metamodels/.* 5 | component_depth: 8 6 | -------------------------------------------------------------------------------- /.github/scripts/build_xatkit.sh: -------------------------------------------------------------------------------- 1 | # This is required because Xatkit is not yet on Maven Central or similar 2 | 3 | # Print a message 4 | e() { 5 | echo -e "$1" 6 | } 7 | 8 | main() { 9 | 10 | # Do not print the build log, it is already available in the Xatkit build 11 | e "Building Required Xatkit Dependencies" 12 | cd /tmp 13 | git clone https://github.com/xatkit-bot-platform/xatkit.git > /dev/null 14 | cd xatkit 15 | git submodule update --init --recursive 16 | mvn clean install -N -DskipTests > /dev/null 17 | cd xatkit-metamodels 18 | git checkout master 19 | mvn clean install -DskipTests > /dev/null 20 | e "Done" 21 | } 22 | 23 | main -------------------------------------------------------------------------------- /.github/scripts/decrypt_ci_cd_secrets.sh: -------------------------------------------------------------------------------- 1 | # This is required because Xatkit is not yet on Maven Central or similar 2 | 3 | # Print a message 4 | e() { 5 | echo -e "$1" 6 | } 7 | 8 | main() { 9 | 10 | e "Decrypting CI/CD secrets" 11 | gpg --quiet --batch --yes --decrypt --passphrase="$CI_CD_KEY" --output ./src/test/resources/xatkit-secrets.zip ./src/test/resources/xatkit-secrets.zip.gpg 12 | unzip ./src/test/resources/xatkit-secrets.zip -d ./src/test/resources/ 13 | } 14 | 15 | main -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Decrypt CI/CD secrets 20 | run: ./.github/scripts/decrypt_ci_cd_secrets.sh 21 | env: 22 | CI_CD_KEY: ${{ secrets.CI_CD_KEY }} 23 | - name: Build Xatkit Parent 24 | run: ./.github/scripts/build_xatkit.sh 25 | - name: Set up JDK 1.8 26 | uses: actions/setup-java@v1 27 | with: 28 | java-version: 1.8 29 | - name: Build with Maven 30 | run: mvn -B package --file pom.xml 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual code classpath 2 | core/.classpath 3 | core/.factorypath 4 | 5 | # Intellij files 6 | .idea 7 | *.iml 8 | 9 | # VisualCode files 10 | .project 11 | 12 | # Compiled class file 13 | *.class 14 | 15 | # Log file 16 | *.log 17 | 18 | # BlueJ files 19 | *.ctxt 20 | 21 | # Mobile Tools for Java (J2ME) 22 | .mtj.tmp/ 23 | 24 | # Package Files # 25 | *.jar 26 | *.war 27 | *.nar 28 | *.ear 29 | *.zip 30 | *.tar.gz 31 | *.rar 32 | 33 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 34 | hs_err_pid* 35 | 36 | # maven 37 | target 38 | **/*.versionsBackup 39 | 40 | # Eclipse 41 | .settings 42 | 43 | # Google App 44 | xatkit-secret.json 45 | xatkit-secrets.tar 46 | xatkit-secrets.zip 47 | gmail_secret.json 48 | credentials 49 | 50 | # Test Variables 51 | **/test-variables.properties 52 | 53 | # Demonstration Projects 54 | jarvisdemo 55 | 56 | # Generated data/ folder 57 | data/ 58 | 59 | # Generated public/ folder 60 | public/ 61 | -------------------------------------------------------------------------------- /.util/build_xatkit.sh: -------------------------------------------------------------------------------- 1 | # This is required because Xatkit is not yet on Maven Central or similar 2 | 3 | # Print a message 4 | e() { 5 | echo -e "$1" 6 | } 7 | 8 | main() { 9 | 10 | # Do not print the build log, it is already available in the Xatkit build 11 | e "Building Required Xatkit Dependencies" 12 | cd /tmp 13 | git clone https://github.com/xatkit-bot-platform/xatkit.git > /dev/null 14 | cd xatkit 15 | git submodule update --init --recursive 16 | mvn clean install -N -DskipTests > /dev/null 17 | cd xatkit-metamodels 18 | git checkout master 19 | mvn clean install -DskipTests > /dev/null 20 | e "Done" 21 | } 22 | 23 | main -------------------------------------------------------------------------------- /.util/publish_javadoc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | JDK="oraclejdk8" 4 | 5 | TYPE="Javadoc" 6 | 7 | DOCS_REPO="$TRAVIS_REPO_SLUG-docs" 8 | 9 | # Print a message 10 | e() { 11 | echo -e "$1" 12 | } 13 | 14 | # Skip the publication with the reason 15 | skip() { 16 | local skipMessage="Skipping $TYPE publication" 17 | 18 | if [ $# -ne 0 ]; then 19 | skipMessage="$skipMessage: $1" 20 | fi 21 | 22 | e "$skipMessage" 23 | exit 1 24 | } 25 | 26 | # Check that the context is valid for publication 27 | checkBuildInfo() { 28 | if [ "$TRAVIS_JDK_VERSION" != "$JDK" ]; then 29 | skip "Wrong JDK. Expected '$JDK' but was '$TRAVIS_JDK_VERSION'" 30 | elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then 31 | skip "Was pull request" 32 | elif [ "$TRAVIS_BRANCH" != "master" ]; then 33 | skip "Wrong branch. Expected 'master' but was '$TRAVIS_BRANCH'" 34 | elif [ "$TRAVIS_OS_NAME" != "linux" ]; then 35 | skip "Wrong OS. Expected 'linux' but was '$TRAVIS_OS_NAME'" 36 | fi 37 | } 38 | 39 | # Generate artifacts 40 | generate() { 41 | e "Generating $TYPE..." 42 | 43 | mvn -q -B javadoc:javadoc javadoc:aggregate -DreportOutputDirectory=$1 -P "deploy-javadoc" 44 | 45 | # Check the generation 46 | if ! [ -d $1 ]; then 47 | skip "No $TYPE has been generated" 48 | fi 49 | } 50 | 51 | # Clone the publication branch 52 | cloneBranch() { 53 | if ! [ -d $1 ]; then 54 | e "Cloning '$1' branch..." 55 | 56 | git config --global user.email "travis@travis-ci.org" 57 | git config --global user.name "travis-ci" 58 | git clone --quiet --branch=$1 https://${GH_TOKEN}@github.com/${DOCS_REPO} $1 59 | fi 60 | } 61 | 62 | # Merge the resulting artifacts, and replace the existing ones 63 | mergeIntoBranch() { 64 | e "Merging $TYPE..." 65 | 66 | # Remove existing artifacts 67 | if [ -d $2 ]; then 68 | git rm --quiet -rf $2 69 | fi 70 | 71 | # Copy new artifacts 72 | mkdir -p $2 73 | cp -Rfp $1/* $2 74 | 75 | git add -Af 76 | 77 | # Check differences 78 | if [ -z "$(git status --porcelain)" ]; then 79 | skip "No change" 80 | fi 81 | } 82 | 83 | # Publish artifacts 84 | publish() { 85 | local commitMessage="[auto] update the $TYPE from Travis #$TRAVIS_BUILD_NUMBER" 86 | 87 | e "Publishing $TYPE..." 88 | 89 | git commit --quiet -m "$commitMessage" 90 | git push --quiet -f origin $1 91 | 92 | e "$TYPE published" 93 | } 94 | 95 | main() { 96 | 97 | local tmpDir=${HOME}/apidocs 98 | 99 | local branch="master" 100 | local branchOutputDir=releases/snapshot/doc 101 | 102 | # Working in the build directory 103 | checkBuildInfo 104 | 105 | generate ${tmpDir} 106 | 107 | # Working in the home directory 108 | cd $HOME 109 | cloneBranch ${branch} 110 | 111 | # Working in branch directory 112 | cd ${branch} 113 | mergeIntoBranch ${tmpDir} ${branchOutputDir} 114 | 115 | publish ${branch} 116 | } 117 | 118 | main 119 | -------------------------------------------------------------------------------- /.util/report_updates.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Print a message 4 | e() { 5 | echo -e "$1" 6 | } 7 | 8 | main() { 9 | 10 | e "Checking dependency versions" 11 | mvn versions:display-dependency-updates 12 | 13 | e "Checking plugin updates" 14 | mvn versions:display-plugin-updates 15 | } 16 | 17 | main 18 | -------------------------------------------------------------------------------- /.util/update_eclipse_dropins.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Update the dropins/ folder of the Eclipse installation used to develop Xatkit languages with the most recently built ones. 4 | 5 | # Fill the XATKIT_ECLIPSE_DROPINS variable with the path of the dropins/ folder of the Eclipse installation. Do not include the last '/' character in the path. 6 | # Fill the XATKIT_VERSION variable with the version number of the Xatkit build. If the version is a snapshot use X.Y.Z-SNAPSHOT 7 | 8 | # If you update this file locally please ignore it using the following command: 9 | # git update-index --skip-worktree update_eclipse_dropins.sh 10 | # If a modification is done on the file upstream git pull will fail, in this case run 11 | # git update-index --no-skip-worktree update_eclipse_dropins.sh 12 | # git stash 13 | # git pull 14 | # git stash pop 15 | # git update-index --skip-worktree update_eclipse_dropins.sh 16 | 17 | #XATKIT_ECLIPSE_DROPINS= 18 | #XATKIT_VERSION= 19 | 20 | if [ -z $XATKIT_ECLIPSE_DROPINS ] 21 | then 22 | echo "Cannot run the script, please set the XATKIT_ECLIPSE_DROPINS variable with the path of the dropins/ folder of your Eclipse installation" 23 | exit 1 24 | fi 25 | 26 | if [ -z $XATKIT_VERSION ] 27 | then 28 | echo "Cannot run the script, please set the XATKIT_VERSION variable with the version number of Xatkit build. If the version is a snapshot use X.Y.Z-SNAPSHOT" 29 | exit 1 30 | fi 31 | 32 | echo "Deleting jars in eclipse/dropins ..." 33 | 34 | rm "$XATKIT_ECLIPSE_DROPINS"/common-*.jar 35 | rm "$XATKIT_ECLIPSE_DROPINS"/core_resources-*.jar 36 | rm "$XATKIT_ECLIPSE_DROPINS"/execution-*.jar 37 | rm "$XATKIT_ECLIPSE_DROPINS"/intent-*.jar 38 | rm "$XATKIT_ECLIPSE_DROPINS"/platform-*.jar 39 | 40 | echo "Done" 41 | 42 | working_directory=$(basename "$(pwd)") 43 | if [ $working_directory == ".util" ] 44 | then 45 | cd .. 46 | working_directory=$(basename "$(pwd)") 47 | fi 48 | if [ $working_directory != "xatkit" ] 49 | then 50 | echo "Cannot execute the script, try to run it from the .util/ directory" 51 | exit 1 52 | fi 53 | 54 | echo "Copying jars ..." 55 | 56 | cp metamodels/common/target/common-"$XATKIT_VERSION".jar $XATKIT_ECLIPSE_DROPINS 57 | cp core_resources/target/core_resources-"$XATKIT_VERSION".jar $XATKIT_ECLIPSE_DROPINS 58 | cp metamodels/execution/target/execution-"$XATKIT_VERSION".jar $XATKIT_ECLIPSE_DROPINS 59 | cp metamodels/intent/target/intent-"$XATKIT_VERSION".jar $XATKIT_ECLIPSE_DROPINS 60 | cp metamodels/platform/target/platform-"$XATKIT_VERSION".jar $XATKIT_ECLIPSE_DROPINS 61 | 62 | echo "Done" 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Xatkit - The easiest way to build complex digital assistants 2 | ====== 3 | [![License Badge](https://img.shields.io/badge/license-EPL%202.0-brightgreen.svg)](https://opensource.org/licenses/EPL-2.0) 4 | [![Java CI with Maven](https://github.com/xatkit-bot-platform/xatkit-runtime/actions/workflows/maven.yml/badge.svg)](https://github.com/xatkit-bot-platform/xatkit-runtime/actions/workflows/maven.yml) 5 | [![codecov](https://codecov.io/gh/xatkit-bot-platform/xatkit-runtime/branch/master/graph/badge.svg)](https://codecov.io/gh/xatkit-bot-platform/xatkit-runtime) 6 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/4f27e0c3177e4417bf99dfac10f3d56b)](https://www.codacy.com/gh/xatkit-bot-platform/xatkit-runtime/dashboard?utm_source=github.com&utm_medium=referral&utm_content=xatkit-bot-platform/xatkit-runtime&utm_campaign=Badge_Grade)[![BCH compliance](https://bettercodehub.com/edge/badge/xatkit-bot-platform/xatkit-runtime?branch=master)](https://bettercodehub.com/) 7 | [![Latest Javadoc Badge](https://img.shields.io/badge/javadoc-latest-brightgreen.svg)](https://xatkit-bot-platform.github.io/xatkit-runtime-docs/releases/snapshot/doc/) 8 | 9 | Xatkit is a generic bot platform that embeds a dedicated **chatbot-specific language** to specify user intentions and received events, and bind them to computable actions. The modeled chatbot definition is handled by this **Xatkit Runtime Engine**, which automatically manages its deployment and execution. 10 | 11 | Spend more time on your conversation design, and let the framework manage the tedious work of deploying the chatbot / digital assistant application, connecting to the targeted platforms, and extract information from user inputs! 12 | 13 | Take a look at the [main Xatkit repository](https://github.com/xatkit-bot-platform/xatkit) and the [Wiki](https://github.com/xatkit-bot-platform/xatkit/wiki) for further instructions on how to install and start creating your own Xatkit bots. 14 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | # Validate before pushing any modification 2 | # cat codecov.yml | curl --data-binary @- https://codecov.io/validate 3 | coverage: 4 | precision: 2 5 | round: down 6 | range: 30...100 7 | 8 | status: 9 | changes: false 10 | patch: true 11 | project: true 12 | 13 | ignore: 14 | # Ignore Exceptions instances 15 | - "**/*Exception.java" 16 | 17 | comment: false 18 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/XatkitException.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core; 2 | 3 | /** 4 | * Xatkit top-level exception. 5 | *

6 | * This exception is used to wrap internal {@link Exception}s and return them in a unified way to client applications. 7 | */ 8 | public class XatkitException extends RuntimeException { 9 | 10 | /** 11 | * Constructs a new {@link XatkitException}. 12 | * 13 | * @see RuntimeException#RuntimeException() 14 | */ 15 | public XatkitException() { 16 | super(); 17 | } 18 | 19 | /** 20 | * Constructs a new {@link XatkitException} from the provided {@code message}. 21 | * 22 | * @param message the exception's message 23 | * @see RuntimeException#RuntimeException(String) 24 | */ 25 | public XatkitException(String message) { 26 | super(message); 27 | } 28 | 29 | /** 30 | * Constructs a new {@link XatkitException} from the provided {@code message} and {@code cause}. 31 | * 32 | * @param message the exception's message 33 | * @param cause the exception's cause 34 | * @see RuntimeException#RuntimeException(String, Throwable) 35 | */ 36 | public XatkitException(String message, Throwable cause) { 37 | super(message, cause); 38 | } 39 | 40 | /** 41 | * Constructs a new {@link XatkitException} from the provided {@code cause}. 42 | * 43 | * @param cause the exception's cause 44 | * @see RuntimeException#RuntimeException(Throwable) 45 | */ 46 | public XatkitException(Throwable cause) { 47 | super(cause); 48 | } 49 | 50 | /** 51 | * Constructs a new {@link XatkitException} from the provided {@code message}, {@code cause}, {@code 52 | * enableSuppression}, and {@code writableStackTrace}. 53 | * 54 | * @param message the exception's message 55 | * @param cause the exception's cause 56 | * @param enableSuppression whether or not suppression is enabled 57 | * @param writableStackTrace whether or not the stack trace should be writable 58 | * @see RuntimeException#RuntimeException(String, Throwable, boolean, boolean) 59 | */ 60 | protected XatkitException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 61 | super(message, cause, enableSuppression, writableStackTrace); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/platform/action/RuntimeActionResult.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.platform.action; 2 | 3 | import lombok.Getter; 4 | 5 | import javax.annotation.Nullable; 6 | 7 | import static fr.inria.atlanmod.commons.Preconditions.checkArgument; 8 | import static java.util.Objects.nonNull; 9 | 10 | /** 11 | * Stores the result of a {@link RuntimeAction} computation and provides utility methods to manipulate it. 12 | *

13 | * This class stores the raw result of a given computation, and can be initialized with additional information 14 | * representing the execution time, and the {@link Exception} thrown by the computation. 15 | *

16 | * {@link RuntimeActionResult} provides an {@link #isError()} method that returns {@code true} if it contains an 17 | * {@link Exception}. This allows to quickly check whether the underlying computation succeeded or failed. 18 | */ 19 | public class RuntimeActionResult { 20 | 21 | /** 22 | * The raw result. 23 | *

24 | * {@link RuntimeActionResult}'s {@code result} value can be set to {@code null} to represent computation results 25 | * that do not return any value. 26 | * 27 | * @see #getResult() 28 | */ 29 | @Getter 30 | private Object result; 31 | 32 | /** 33 | * The execution time (in milliseconds). 34 | * 35 | * @see #getExecutionTime() 36 | */ 37 | @Getter 38 | private long executionTime; 39 | 40 | /** 41 | * Represents an error result with an {@link Exception}. 42 | *

43 | * Setting this value makes the {@link #isError()} method return {@code true}. 44 | * 45 | * @see #getThrowable() 46 | * @see #isError() 47 | */ 48 | @Getter 49 | private Throwable throwable; 50 | 51 | /** 52 | * Constructs a new {@link RuntimeActionResult} from the provided {@code result} and {@code executionTime}. 53 | *

54 | * This constructor does not set any {@code thrownException} value. As a result, calling the {@link #isError()} 55 | * method will return {@code false}. 56 | * 57 | * @param result the raw result 58 | * @param executionTime the execution time (in milliseconds) 59 | * @throws IllegalArgumentException if the provided {@code executionTime < 0} 60 | */ 61 | public RuntimeActionResult(Object result, long executionTime) { 62 | this(result, null, executionTime); 63 | } 64 | 65 | /** 66 | * Constructs a new {@link RuntimeActionResult} from the provided {@code partialResult}, {@code thrownException}, 67 | * and {@code executionTime}. 68 | *

69 | * This constructor sets the {@code thrownException} attribute, meaning that calling {@link #isError()} on this 70 | * object will return {@code true}. The {@code partialResult} can be used to represent partial information that 71 | * has been computed before the provided {@link Exception} was thrown. 72 | *

73 | * This constructor sets the {@code executionTime} attribute, that can be accessed through the 74 | * {@link #getExecutionTime()} method. 75 | * 76 | * @param partialResult the partial raw result that has been computed before failing 77 | * @param throwable the {@link Throwable} that has been thrown during the computation 78 | * @param executionTime the execution time (in milliseconds) 79 | * @throws IllegalArgumentException if the provided {@code executionTime < 0} 80 | */ 81 | public RuntimeActionResult(@Nullable Object partialResult, @Nullable Throwable throwable, long executionTime) { 82 | checkArgument(executionTime >= 0, "Cannot construct a %s from the provided execution time: expected a " 83 | + "positive value (in ms), found %s", this.getClass().getSimpleName(), executionTime); 84 | this.result = partialResult; 85 | this.throwable = throwable; 86 | this.executionTime = executionTime; 87 | } 88 | 89 | /** 90 | * Returns whether the {@link RuntimeActionResult} represents an errored computation. 91 | *

92 | * If this method returns {@code true} the {@link Exception} that has been thrown during the errored computation 93 | * can be retrieved by calling {@link #getThrowable()}. 94 | * 95 | * @return {@code true} if the {@link RuntimeActionResult} represents an errored computation, {@code false} 96 | * otherwise 97 | * @see #getThrowable() 98 | */ 99 | public boolean isError() { 100 | return nonNull(this.throwable); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/platform/action/RuntimeMessageAction.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.platform.action; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.execution.StateContext; 5 | import lombok.Getter; 6 | import lombok.NonNull; 7 | 8 | import static fr.inria.atlanmod.commons.Preconditions.checkArgument; 9 | 10 | /** 11 | * An abstract {@link RuntimeAction} processing a message. 12 | *

13 | * 14 | * @param the concrete {@link RuntimePlatform} subclass type containing the action 15 | * @see RuntimePlatform 16 | */ 17 | public abstract class RuntimeMessageAction extends RuntimeArtifactAction { 18 | 19 | /** 20 | * The processed message. 21 | * 22 | * @see #getMessage() 23 | */ 24 | @Getter 25 | protected String message; 26 | 27 | /** 28 | * Constructs a new {@link RuntimeMessageAction} with the provided {@code platform}, {@code context}, and 29 | * {@code rawMessage}. 30 | *

31 | * 32 | * @param platform the {@link RuntimePlatform} containing this action 33 | * @param context the {@link StateContext} associated to this action 34 | * @param rawMessage the message to process 35 | * @throws NullPointerException if the provided {@code platform}, {@code context}, or {@code 36 | * rawMessage} is {@code null} 37 | * @throws IllegalArgumentException if the provided {@code rawMessage} is {@code null} or empty 38 | * @see StateContext 39 | */ 40 | public RuntimeMessageAction(@NonNull T platform, @NonNull StateContext context, @NonNull String rawMessage) { 41 | super(platform, context); 42 | checkArgument(!rawMessage.isEmpty(), "Cannot construct a %s action with the provided message %s, expected a " 43 | + "non-null and not empty String", this.getClass().getSimpleName(), message); 44 | this.message = rawMessage; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/platform/io/IntentRecognitionHelper.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.platform.io; 2 | 3 | import com.xatkit.core.XatkitBot; 4 | import com.xatkit.core.recognition.IntentRecognitionProviderException; 5 | import com.xatkit.execution.StateContext; 6 | import com.xatkit.intent.RecognizedIntent; 7 | import fr.inria.atlanmod.commons.log.Log; 8 | import lombok.NonNull; 9 | 10 | import java.util.stream.Collectors; 11 | 12 | /** 13 | * A helper class that provides method to extract intents from input text. 14 | *

15 | * This class can be used by {@link RuntimeEventProvider}s that receive user messages and translate them to 16 | * intents. It automatically manages the recognition as well as the session attributes that need to be updated 17 | * once an intent has been recognized. 18 | */ 19 | public class IntentRecognitionHelper { 20 | 21 | /** 22 | * Disables the default constructor, this class only provides static methods and should not be constructed. 23 | */ 24 | private IntentRecognitionHelper() { } 25 | 26 | /** 27 | * Returns the {@link RecognizedIntent} from the provided user {@code input} and {@code session}. 28 | *

29 | * This uses the provided {@code xatkitBot} to wrap the access to the underlying 30 | * {@link com.xatkit.core.recognition.IntentRecognitionProvider}, and avoid uncontrolled accesses to the 31 | * {@link com.xatkit.core.recognition.IntentRecognitionProvider} from {@link RuntimeEventProvider}s (such as 32 | * intent creation, removal, and context manipulation). 33 | * 34 | * @param input the textual user input to extract the {@link RecognizedIntent} from 35 | * @param context the {@link StateContext} wrapping the underlying 36 | * {@link com.xatkit.core.recognition.IntentRecognitionProvider}'s session 37 | * @return the {@link RecognizedIntent} computed by the 38 | * {@link com.xatkit.core.recognition.IntentRecognitionProvider} 39 | * @throws NullPointerException if the provided {@code text} or {@code session} is {@code null} 40 | * @throws IllegalArgumentException if the provided {@code text} is empty 41 | * @throws IntentRecognitionProviderException if the 42 | * {@link com.xatkit.core.recognition.IntentRecognitionProvider} is 43 | * shutdown or if an exception is thrown by the 44 | * underlying intent recognition engine 45 | */ 46 | public static RecognizedIntent getRecognizedIntent(@NonNull String input, @NonNull StateContext context, 47 | @NonNull XatkitBot xatkitBot) 48 | throws IntentRecognitionProviderException { 49 | RecognizedIntent recognizedIntent = xatkitBot.getIntentRecognitionProvider().getIntent(input, context); 50 | Log.info("Detected Intent {0} (confidence {1}) from query text \"{2}\"{3}", 51 | recognizedIntent.getDefinition().getName(), recognizedIntent.getRecognitionConfidence(), 52 | recognizedIntent.getMatchedInput(), printIntentParameters(recognizedIntent)); 53 | return recognizedIntent; 54 | } 55 | 56 | /** 57 | * Prints a {@link String} representation of the provided {@code recognizedIntent}'s parameter values. 58 | * 59 | * @param recognizedIntent the {@link RecognizedIntent} to print the parameter values of 60 | * @return a {@link String} representation of the provided {@code recognizedIntent}'s parameter values 61 | */ 62 | private static String printIntentParameters(RecognizedIntent recognizedIntent) { 63 | if (recognizedIntent.getValues().isEmpty()) { 64 | return ""; 65 | } else { 66 | String parameters = 67 | recognizedIntent.getValues().stream() 68 | .map(p -> p.getContextParameter().getName() + "=\"" + p.getValue().toString() + "\"") 69 | .collect(Collectors.joining(", ", "{", "}")); 70 | return "\nIntent Parameters: " + parameters; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/platform/io/RuntimeEventProvider.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.platform.io; 2 | 3 | import com.xatkit.core.XatkitBot; 4 | import com.xatkit.core.platform.RuntimePlatform; 5 | import com.xatkit.execution.StateContext; 6 | import com.xatkit.intent.EventInstance; 7 | import lombok.NonNull; 8 | import org.apache.commons.configuration2.Configuration; 9 | 10 | /** 11 | * Generates {@link EventInstance}s that can be used by a Xatkit bot. 12 | *

13 | * This class maps received inputs (e.g. REST request, user message, socket event) to {@link EventInstance}s that are 14 | * used by the Xatkit engine. 15 | * 16 | * @param the {@link RuntimePlatform} containing the provider 17 | */ 18 | public abstract class RuntimeEventProvider implements Runnable { 19 | 20 | /** 21 | * The {@link XatkitBot} instance used to handle events. 22 | *

23 | * This attribute is a shortcut for {@code runtimePlatform.getXatkitBot()}. 24 | */ 25 | protected XatkitBot xatkitBot; 26 | 27 | /** 28 | * The {@link RuntimePlatform} subclass containing this action. 29 | */ 30 | protected T runtimePlatform; 31 | 32 | /** 33 | * Creates an unstarted {@link RuntimeEventProvider} managed by the provided {@code platform}. 34 | *

35 | * As for {@link RuntimePlatform}, this constructor does not have access to the {@link XatkitBot} nor the 36 | * {@link Configuration}: it is typically called when defining a bot to have a usable reference to set in the bot 37 | * execution model, but it is initialized during the bot deployment using the 38 | * {@link RuntimeEventProvider#start(Configuration)} method. 39 | * 40 | * @param platform the {@link RuntimePlatform} managing this provider 41 | */ 42 | public RuntimeEventProvider(@NonNull T platform) { 43 | this.runtimePlatform = platform; 44 | } 45 | 46 | /** 47 | * Starts the provider. 48 | *

49 | * This method takes as input the bot {@code configuration} that can contain specific properties to customize the 50 | * provider (e.g. to filter some input). Subclasses typically override this method to initialize their internal 51 | * data structure and register REST handlers to receive push events. 52 | *

53 | * This method is automatically called bu Xatkit when a bot using this provider is starting. 54 | *

55 | * Note that the {@link XatkitBot} instance is bound to the provider when calling this method. 56 | * 57 | * @param configuration the {@link Configuration} of the bot currently run 58 | * @see RuntimePlatform#startEventProvider(RuntimeEventProvider) 59 | */ 60 | public void start(@NonNull Configuration configuration) { 61 | this.xatkitBot = runtimePlatform.getXatkitBot(); 62 | this.runtimePlatform.startEventProvider(this); 63 | } 64 | 65 | /** 66 | * Returns the {@link RuntimePlatform} containing this {@link RuntimeEventProvider}. 67 | * 68 | * @return the {@link RuntimePlatform} containing this {@link RuntimeEventProvider} 69 | */ 70 | public T getRuntimePlatform() { 71 | return runtimePlatform; 72 | } 73 | 74 | /** 75 | * Sends the provided {@code eventInstance} and {@code session} for computation to the Xatkit core component. 76 | *

77 | * This method sets the triggeredBy field of the provided {@code eventInstance} with the name of the 78 | * containing platform of this provider. 79 | *

80 | * This method can be extended to perform specific checks before triggering actions (e.g. ensure that a specific 81 | * context variable has been set). 82 | * 83 | * @param eventInstance the {@link EventInstance} to send to the Xatkit core component 84 | * @param context the {@link StateContext} associated to the provided {@code eventInstance} 85 | */ 86 | public void sendEventInstance(EventInstance eventInstance, StateContext context) { 87 | eventInstance.setTriggeredBy(this.runtimePlatform.getName()); 88 | this.xatkitBot.getExecutionService().handleEventInstance(eventInstance, context); 89 | } 90 | 91 | public void broadcastEventInstance(EventInstance eventInstance) { 92 | eventInstance.setTriggeredBy(this.runtimePlatform.getName()); 93 | this.xatkitBot.getContexts().forEach(context -> 94 | this.xatkitBot.getExecutionService().handleEventInstance(eventInstance, context) 95 | ); 96 | } 97 | 98 | /** 99 | * Closes the {@link RuntimeEventProvider} and releases internal resources. 100 | *

101 | * This method should be overridden by concrete subclasses that manipulate internal resources that require to be 102 | * explicitly closed. 103 | */ 104 | public void close() { 105 | 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/platform/io/WebhookEventProvider.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.platform.io; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.core.server.HttpMethod; 5 | import com.xatkit.core.server.RestHandler; 6 | import lombok.NonNull; 7 | import org.apache.commons.configuration2.Configuration; 8 | 9 | /** 10 | * A specialised {@link RuntimeEventProvider} that handles Rest requests sent by the Xatkit server. 11 | *

12 | * Concrete subclasses must implement the {@link #getEndpointURI()} that sets the URI to register the provider 13 | * to, and {@link #createRestHandler()} that creates the concrete {@link RestHandler} instance handling incoming Rest 14 | * requests. 15 | * 16 | * @param the concrete {@link RuntimePlatform} subclass type containing the provider 17 | * @param the {@link RestHandler} type processing incoming Rest requests 18 | * @see RestHandler 19 | * @see com.xatkit.core.server.RestHandlerFactory 20 | */ 21 | public abstract class WebhookEventProvider 22 | extends RuntimeEventProvider { 23 | 24 | /** 25 | * The {@link RestHandler} used to process incoming Rest requests. 26 | */ 27 | private H restHandler; 28 | 29 | /** 30 | * Creates an unstarted {@link WebhookEventProvider} managed by the provided {@code platform}. 31 | *

32 | * As for {@link RuntimeEventProvider}, this constructor does not have access to the Xatkit bot nor the 33 | * {@link Configuration}: it is typically called when defining a bot to have a usable reference to set in 34 | * the bot execution model, but it is initialized during the bot deployment using the 35 | * {@link WebhookEventProvider#start(Configuration)} method. 36 | * 37 | * @param platform the {@link RuntimePlatform} managing this provider 38 | */ 39 | public WebhookEventProvider(T platform) { 40 | super(platform); 41 | } 42 | 43 | /** 44 | * Starts the provider and registers its {@link RestHandler}. 45 | * 46 | * @param configuration the {@link Configuration} of the bot currently run 47 | */ 48 | @Override 49 | public void start(@NonNull Configuration configuration) { 50 | this.restHandler = createRestHandler(); 51 | super.start(configuration); 52 | } 53 | 54 | /** 55 | * Returns the URI of the REST endpoint to register the provider to. 56 | *

57 | * The returned {@link String} must be prefixed by a {@code '/'}. 58 | * 59 | * @return the URI of the Rest endpoint to register the provider to 60 | */ 61 | public abstract String getEndpointURI(); 62 | 63 | /** 64 | * Returns the {@link HttpMethod} of the REST endpoint to register the provided to. 65 | *

66 | * This method returns {@link HttpMethod#POST} by default, subclasses can override this method to return custom 67 | * {@link HttpMethod}. 68 | * 69 | * @return the {@link HttpMethod} of the REST endpoint to register the provider to 70 | */ 71 | public HttpMethod getEndpointMethod() { 72 | return HttpMethod.POST; 73 | } 74 | 75 | /** 76 | * Returns the concrete {@link RestHandler} instance that handles incoming Rest requests. 77 | *

78 | * This handler can be defined with the utility methods provided in 79 | * {@link com.xatkit.core.server.RestHandlerFactory}. 80 | * 81 | * @return the concrete {@link RestHandler} instance that handles incoming Rest requests 82 | * @see com.xatkit.core.server.RestHandlerFactory 83 | */ 84 | protected abstract H createRestHandler(); 85 | 86 | /** 87 | * Returns the {@link RestHandler} embedded in this provider. 88 | * 89 | * @return the {@link RestHandler} embedded in this provider 90 | */ 91 | public H getRestHandler() { 92 | return this.restHandler; 93 | } 94 | 95 | /** 96 | * Runs the provider. 97 | */ 98 | @Override 99 | public void run() { 100 | synchronized (this) { 101 | try { 102 | wait(); 103 | } catch (InterruptedException e) { 104 | 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/recognition/DefaultFallbackIntent.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition; 2 | 3 | import com.xatkit.intent.impl.IntentDefinitionImpl; 4 | 5 | /** 6 | * An {@link com.xatkit.intent.IntentDefinition} representing the default fallback. 7 | */ 8 | public class DefaultFallbackIntent extends IntentDefinitionImpl { 9 | 10 | /** 11 | * Constructs a new {@link DefaultFallbackIntent}. 12 | */ 13 | DefaultFallbackIntent() { 14 | super(); 15 | this.name = "Default_Fallback_Intent"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/recognition/IntentRecognitionProviderException.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition; 2 | 3 | 4 | /** 5 | * Wraps all the exceptions thrown by the {@link IntentRecognitionProvider}s. 6 | */ 7 | public class IntentRecognitionProviderException extends Exception { 8 | 9 | /** 10 | * Constructs a new {@link IntentRecognitionProviderException}. 11 | * 12 | * @see RuntimeException#RuntimeException() 13 | */ 14 | public IntentRecognitionProviderException() { 15 | super(); 16 | } 17 | 18 | /** 19 | * Constructs a new {@link IntentRecognitionProviderException} from the provided {@code message}. 20 | * 21 | * @param message the exception's message 22 | * @see RuntimeException#RuntimeException(String) 23 | */ 24 | public IntentRecognitionProviderException(String message) { 25 | super(message); 26 | } 27 | 28 | /** 29 | * Constructs a new {@link IntentRecognitionProviderException} from the provided {@code message} and {@code cause}. 30 | * 31 | * @param message the exception's message 32 | * @param cause the exception's cause 33 | * @see RuntimeException#RuntimeException(String, Throwable) 34 | */ 35 | public IntentRecognitionProviderException(String message, Throwable cause) { 36 | super(message, cause); 37 | } 38 | 39 | /** 40 | * Constructs a new {@link IntentRecognitionProviderException} from the provided {@code cause}. 41 | * 42 | * @param cause the exception's cause 43 | * @see RuntimeException#RuntimeException(Throwable) 44 | */ 45 | public IntentRecognitionProviderException(Throwable cause) { 46 | super(cause); 47 | } 48 | 49 | /** 50 | * Constructs a new {@link IntentRecognitionProviderException} from the provided {@code message}, {@code cause}, 51 | * {@code enableSuppression}, and {@code writableStackTrace}. 52 | * 53 | * @param message the exception's message 54 | * @param cause the exception's cause 55 | * @param enableSuppression whether or not suppression is enabled or disabled 56 | * @param writableStackTrace whether or not stack trace should be writable 57 | */ 58 | public IntentRecognitionProviderException(String message, Throwable cause, boolean enableSuppression, boolean 59 | writableStackTrace) { 60 | super(message, cause, enableSuppression, writableStackTrace); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/recognition/IntentRecognitionProviderFactoryConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition; 2 | 3 | import lombok.NonNull; 4 | import lombok.Value; 5 | import org.apache.commons.configuration2.Configuration; 6 | 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | 12 | import static java.util.Objects.isNull; 13 | 14 | /** 15 | * Contains {@link IntentRecognitionProviderFactory} configuration. 16 | *

17 | * This class is initialized with a {@link Configuration} instance, and takes care of extracting the 18 | * {@link IntentRecognitionProviderFactory}-related properties. 19 | *

20 | * The base {@link Configuration} used to initialize this class can be accessed through {@link #getBaseConfiguration()}. 21 | */ 22 | @Value 23 | public class IntentRecognitionProviderFactoryConfiguration { 24 | 25 | /** 26 | * The {@link Configuration} key used to specify whether to enable intent recognition monitoring. 27 | *

28 | * Intent recognition monitoring is enabled by default, and stores the results in the {@code data/analytics} 29 | * folder. It can be disabled by explicitly setting this property to {@code false} in the {@link Configuration} 30 | * file. 31 | */ 32 | public static final String ENABLE_RECOGNITION_ANALYTICS = "xatkit.recognition.enable_monitoring"; 33 | 34 | /** 35 | * The {@link Configuration} key used to specify the 36 | * {@link com.xatkit.core.recognition.processor.InputPreProcessor}s to add to the created 37 | * {@link IntentRecognitionProvider}. 38 | *

39 | * {@link com.xatkit.core.recognition.processor.InputPreProcessor}s are specified as a comma-separated list of 40 | * processor's names. 41 | */ 42 | public static final String RECOGNITION_PREPROCESSORS_KEY = "xatkit.recognition.preprocessors"; 43 | 44 | /** 45 | * The {@link Configuration} key used to specify the 46 | * {@link com.xatkit.core.recognition.processor.IntentPostProcessor}s to add to the created 47 | * {@link IntentRecognitionProvider}. 48 | *

49 | * {@link com.xatkit.core.recognition.processor.IntentPostProcessor}s are specified as a comma-separated list of 50 | * processor's names. 51 | */ 52 | public static final String RECOGNITION_POSTPROCESSORS_KEY = "xatkit.recognition.postprocessors"; 53 | 54 | /** 55 | * The base {@link Configuration} used to initialize the {@link IntentRecognitionProviderFactoryConfiguration}. 56 | */ 57 | private Configuration baseConfiguration; 58 | 59 | /** 60 | * A flag to enable/disable recognition analytics. 61 | */ 62 | private boolean enableRecognitionAnalytics; 63 | 64 | /** 65 | * The list of preprocessor names to add to the created {@link IntentRecognitionProvider}. 66 | */ 67 | private List preProcessorNames; 68 | 69 | /** 70 | * The list of postprocessor names to add to the created {@link IntentRecognitionProvider}. 71 | */ 72 | private List postProcessorNames; 73 | 74 | /** 75 | * Initializes the {@link IntentRecognitionProviderFactoryConfiguration} with the provided {@code 76 | * baseConfiguration}. 77 | * 78 | * @param baseConfiguration the {@link Configuration} to load the values from 79 | * @throws NullPointerException if the provided {@code baseConfiguration} is {@code null} 80 | */ 81 | public IntentRecognitionProviderFactoryConfiguration(@NonNull Configuration baseConfiguration) { 82 | this.baseConfiguration = baseConfiguration; 83 | this.enableRecognitionAnalytics = baseConfiguration.getBoolean(ENABLE_RECOGNITION_ANALYTICS, false); 84 | this.preProcessorNames = getList(baseConfiguration, RECOGNITION_PREPROCESSORS_KEY); 85 | this.postProcessorNames = getList(baseConfiguration, RECOGNITION_POSTPROCESSORS_KEY); 86 | } 87 | 88 | /** 89 | * Returns a {@link List} extracted from the value associated to the provided {@code key} in the given {@code 90 | * configuration}. 91 | *

92 | * Note: this method is a workaround, the correct way to implement it is to use {@code configuration 93 | * .setListDelimiterHandler}, but this method does not work with the DefaultConversionHandler embedded in the 94 | * configuration. 95 | * 96 | * @param configuration the {@link Configuration} to get the {@link List} from 97 | * @param key the key to retrieve the {@link List} from 98 | * @return the {@link List}, or {@code null} if the provided {@code key} is not contained in the {@code 99 | * configuration} 100 | */ 101 | private @NonNull List getList(@NonNull Configuration configuration, @NonNull String key) { 102 | String value = configuration.getString(key); 103 | if (isNull(value)) { 104 | return Collections.emptyList(); 105 | } 106 | return Arrays.stream(value.split(",")).map(String::trim).collect(Collectors.toList()); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/recognition/RecognitionMonitor.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition; 2 | 3 | import com.xatkit.execution.StateContext; 4 | import com.xatkit.intent.RecognizedIntent; 5 | 6 | public interface RecognitionMonitor { 7 | 8 | /** 9 | * Logs the recognition information from the provided {@code recognizedIntent} and {@code session}. 10 | * 11 | * @param context the {@link StateContext} from which the {@link RecognizedIntent} has been created 12 | * @param intent the {@link RecognizedIntent} to log 13 | */ 14 | void logRecognizedIntent(StateContext context, RecognizedIntent intent); 15 | 16 | /** 17 | * Closes the connection to the database. 18 | */ 19 | void shutdown(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/recognition/processor/InputPreProcessor.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition.processor; 2 | 3 | import com.xatkit.execution.StateContext; 4 | 5 | /** 6 | * Applies a pre-processing function on the provided {@code input}. 7 | *

8 | * This interface is a functional interface, client code can create an {@link InputPreProcessor} with the following 9 | * code: {@code (input, context} -> { // pre-processing }}. 10 | */ 11 | @FunctionalInterface 12 | public interface InputPreProcessor { 13 | 14 | /** 15 | * Initializes the pre-processor. 16 | *

17 | * This method is called after the construction of all the pre-processors, and can be used to initialize 18 | * services used by multiple pre-processors (e.g. a NLP service that needs to be warmed-up). 19 | *

20 | * Sub-classes should override this method if they need to perform initialization steps that cannot be performed 21 | * when constructing the pre-processors. 22 | */ 23 | default void init() { 24 | } 25 | 26 | /** 27 | * Processes the provided {@code input}. 28 | *

29 | * This method is called with the {@code session} associated to the provided {@code input} in order to define 30 | * advanced pre-processing functions taking into account session's content. 31 | * 32 | * @param input the input to process 33 | * @param context the {@link StateContext} associated to the {@code input} 34 | * @return the processed {@code input} 35 | */ 36 | String process(String input, StateContext context); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/recognition/processor/IntentPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition.processor; 2 | 3 | import com.xatkit.execution.StateContext; 4 | import com.xatkit.intent.RecognizedIntent; 5 | 6 | /** 7 | * Applies a post-processing function on the provided {@code recognizedIntent}. 8 | *

9 | * This interface is a functional interface, client code can create an {@link IntentPostProcessor} with the following 10 | * code: {@code (recognizedIntent, context) -> { // post-processing }}. 11 | */ 12 | @FunctionalInterface 13 | public interface IntentPostProcessor { 14 | 15 | /** 16 | * Initializes the post-processor. 17 | *

18 | * This method is called after the construction of all the post-processors, and can be used to initialize 19 | * services used by multiple post-processors (e.g. a NLP service that needs to be warmed-up). 20 | *

21 | * Sub-classes should override this method if they need to perform initialization steps that cannot be performed 22 | * when constructing the post-processor. 23 | */ 24 | default void init() { 25 | } 26 | 27 | /** 28 | * Processes the provided {@code recognizedIntent}. 29 | *

30 | * This method is called with the {@code session} associated to the provided {@code recognizedIntent} in order to 31 | * define advanced post-processing functions taking into account session's content. 32 | * 33 | * @param recognizedIntent the {@link RecognizedIntent} to process 34 | * @param context the {@link StateContext} associated to the {@code recognizedIntent} 35 | * @return the processed {@code recognizedIntent} 36 | */ 37 | RecognizedIntent process(RecognizedIntent recognizedIntent, StateContext context); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/recognition/regex/RegExEntityMapper.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition.regex; 2 | 3 | 4 | import com.xatkit.core.recognition.EntityMapper; 5 | import com.xatkit.intent.EntityDefinition; 6 | 7 | /** 8 | * An {@link EntityMapper} that uses RegExp to match system entities. 9 | *

10 | * This class matches all the system entities using the same RegExp ((\D)+), meaning that system entities can only be 11 | * matched from a single word. 12 | *

13 | * Custom entities can be registered using {@link #addEntityMapping(EntityDefinition, String)} and associated to the 14 | * RegExp pattern that will be used to retrieve them. 15 | */ 16 | public class RegExEntityMapper extends EntityMapper { 17 | 18 | /** 19 | * Constructs a {@link RegExEntityMapper} that uses RegExp to match system entities. 20 | */ 21 | public RegExEntityMapper() { 22 | super(); 23 | this.setFallbackEntityMapping("(\\S)+"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/server/ContentHttpHandler.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.server; 2 | 3 | import fr.inria.atlanmod.commons.log.Log; 4 | import org.apache.http.HttpRequest; 5 | import org.apache.http.HttpResponse; 6 | import org.apache.http.HttpStatus; 7 | import org.apache.http.entity.BasicHttpEntity; 8 | import org.apache.http.protocol.HttpContext; 9 | import org.apache.http.protocol.HttpRequestHandler; 10 | 11 | import java.io.File; 12 | import java.io.FileInputStream; 13 | import java.io.IOException; 14 | import java.util.Locale; 15 | 16 | import static java.util.Objects.nonNull; 17 | 18 | /** 19 | * Handles the HTTP requests performed on the {@code /content/} path. 20 | *

21 | * This handler is designed to server public files. It only accepts GET requests, and do not take into account query 22 | * parameters. 23 | *

24 | * Accessible files are stored in the {@code } directory, and can be accessed using the following URL 25 | * template: {@code }. 26 | */ 27 | public class ContentHttpHandler implements HttpRequestHandler { 28 | 29 | /** 30 | * The {@link XatkitServer} managing this handler. 31 | */ 32 | private XatkitServer xatkitServer; 33 | 34 | /** 35 | * Constructs a new {@link ContentHttpHandler} managed by the provided {@code xatkitServer}. 36 | * 37 | * @param xatkitServer the {@link XatkitServer} managing this handler. 38 | */ 39 | public ContentHttpHandler(XatkitServer xatkitServer) { 40 | super(); 41 | this.xatkitServer = xatkitServer; 42 | } 43 | 44 | /** 45 | * Handles the received {@code request} and fill the provided {@code response} with the retrieved {@link File} to 46 | * serve. 47 | *

48 | * This method relies on {@link XatkitServer#getPublicFile(String)} to retrieve the public file associated to the 49 | * request target. If this {@link File} doesn't exist or the accessed location is illegal the response is set to 50 | * {@link HttpStatus#SC_NOT_FOUND}. 51 | * 52 | * @param request the received {@link HttpRequest} 53 | * @param response the {@link HttpResponse} to send to the caller 54 | * @param context the {@link HttpContext} associated to the received {@link HttpRequest} 55 | */ 56 | @Override 57 | public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) { 58 | 59 | String method = request.getRequestLine().getMethod().toUpperCase(Locale.ROOT); 60 | String target = request.getRequestLine().getUri(); 61 | 62 | Log.debug("{0} - Received a {1} query on {2}", this.getClass().getSimpleName(), method, target); 63 | 64 | /* 65 | * Ignore the parameters, they are not used for now. 66 | */ 67 | if (method.equals("GET")) { 68 | if (target.startsWith(XatkitServerUtils.PUBLIC_CONTENT_URL_FRAGMENT)) { 69 | String filePath = target.replaceFirst(XatkitServerUtils.PUBLIC_CONTENT_URL_FRAGMENT, ""); 70 | Log.debug("File Path: {0}", filePath); 71 | File file = xatkitServer.getPublicFile(filePath); 72 | if (nonNull(file) && file.exists() && !file.isDirectory()) { 73 | FileInputStream fis; 74 | try { 75 | fis = new FileInputStream(file); 76 | } catch (IOException e) { 77 | Log.error("{0} Cannot retrieve the file {1}", this.getClass().getSimpleName(), 78 | file.getAbsolutePath()); 79 | response.setStatusCode(HttpStatus.SC_NOT_FOUND); 80 | return; 81 | } 82 | BasicHttpEntity entity = new BasicHttpEntity(); 83 | entity.setContent(fis); 84 | response.setEntity(entity); 85 | response.setStatusCode(HttpStatus.SC_OK); 86 | return; 87 | } 88 | } 89 | } 90 | Log.error("Cannot server content {0}, unsupported method {1}", target, method); 91 | response.setStatusCode(HttpStatus.SC_NOT_FOUND); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/server/EmptyContentRestHandler.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.server; 2 | 3 | import org.apache.http.Header; 4 | import org.apache.http.NameValuePair; 5 | 6 | import javax.annotation.Nonnull; 7 | import javax.annotation.Nullable; 8 | import java.util.List; 9 | 10 | import static fr.inria.atlanmod.commons.Preconditions.checkArgument; 11 | import static java.util.Objects.isNull; 12 | 13 | /** 14 | * A handler that receives HTTP requests with empty content and process them. 15 | *

16 | * This class can be used to define REST endpoints from {@link com.xatkit.core.platform.RuntimePlatform}s. The 17 | * endpoint can be registered using the following code: 18 | *

19 |  * {@code
20 |  * XatkitServer xatkitServer = [...]
21 |  * String restEndpointURI = "/myEndpoint";
22 |  * xatkitServer.registerRestEndpoint(HttpMethod.GET, restEndpointURI, RestHandlerFactory.createEmptyContentRestHandler(
23 |  *  (headers, params, content) -> {
24 |  *      // Handle the request
25 |  *      // return an Object that will be embedded in the HTTP response
26 |  *  }
27 |  * }
28 |  * 
29 | */ 30 | public abstract class EmptyContentRestHandler extends RestHandler { 31 | 32 | /** 33 | * Returns {@code true}. 34 | *

35 | * This handler accepts any content type, but will throw an exception if the request's content is not empty. 36 | * 37 | * @param contentType the content type to check 38 | * @return {@code true} 39 | */ 40 | @Override 41 | public boolean acceptContentType(String contentType) { 42 | return true; 43 | } 44 | 45 | /** 46 | * Checks that the provided {@code content} object is {@code null} and returns it. 47 | *

48 | * This method throws an exception if the provided {@code content} object is not {@code null}. The handler does 49 | * not support request's content, see other handlers to deal with specific content type (e.g. 50 | * {@link JsonRestHandler}). 51 | * 52 | * @param content the raw HTTP request content to parse 53 | * @return {@code null} 54 | * @throws IllegalArgumentException if the provided {@code content} is not null 55 | */ 56 | @Nullable 57 | @Override 58 | protected Object parseContent(@Nullable Object content) { 59 | checkArgument(isNull(content), "Cannot parse the provided content %s, %s expects empty requests (with null " 60 | + "content)", content, this.getClass().getSimpleName()); 61 | return null; 62 | } 63 | 64 | /** 65 | * Handles the request. 66 | *

67 | * Note: the {@code content} object is always {@code null} (this handler does not support request's content). 68 | * 69 | * @param headers the HTTP headers of the received request 70 | * @param params the request parameters 71 | * @param content the parsed request payload to handle 72 | * @return the handler's result 73 | * @throws RestHandlerException if an error occurred when handling the request 74 | */ 75 | @Nullable 76 | @Override 77 | protected abstract Object handleParsedContent(@Nonnull List

headers, @Nonnull List params, 78 | @Nullable Object content) throws RestHandlerException; 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/server/HttpMethod.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.server; 2 | 3 | /** 4 | * Utility enum holding supported Http methods. 5 | */ 6 | public enum HttpMethod { 7 | 8 | GET("GET"), 9 | POST("POST"), 10 | DELETE("DELETE"), 11 | HEAD("HEAD"), 12 | OPTIONS("OPTIONS"), 13 | PATCH("PATCH"), 14 | PUT("PUT"), 15 | TRACE("TRACE"); 16 | 17 | /** 18 | * The literal of the enum value. 19 | */ 20 | public final String label; 21 | 22 | /** 23 | * Constructs a new enum value with the provided {@code label}. 24 | * 25 | * @param label the label of the enum value 26 | */ 27 | HttpMethod(String label) { 28 | this.label = label; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/server/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.server; 2 | 3 | import org.apache.http.HttpRequest; 4 | import org.apache.http.NameValuePair; 5 | import org.apache.http.client.utils.URIBuilder; 6 | 7 | import javax.annotation.Nonnull; 8 | import javax.annotation.Nullable; 9 | import java.net.URISyntaxException; 10 | import java.util.List; 11 | 12 | import static fr.inria.atlanmod.commons.Preconditions.checkNotNull; 13 | 14 | /** 15 | * Provides utility methods to manipulate Http-related objects. 16 | */ 17 | public final class HttpUtils { 18 | 19 | /** 20 | * Disables the default constructor, this class only provides static methods and should not be constructed. 21 | */ 22 | private HttpUtils() { 23 | } 24 | 25 | /** 26 | * Returns a {@link URIBuilder} from the provided {@code httpRequest}. 27 | * 28 | * @param httpRequest the {@link HttpRequest} to get an {@link URIBuilder} from 29 | * @return the created {@link URIBuilder} 30 | * @throws URISyntaxException if the provided {@code httpRequest}'s URI is invalid 31 | */ 32 | public static URIBuilder getURIBuilderFrom(@Nonnull HttpRequest httpRequest) throws URISyntaxException { 33 | checkNotNull(httpRequest, "Cannot create an %s from the provided %s %s", URIBuilder.class.getSimpleName(), 34 | HttpRequest.class.getSimpleName(), httpRequest); 35 | return new URIBuilder(httpRequest.getRequestLine().getUri()); 36 | } 37 | 38 | /** 39 | * Returns the path associated to the provided {@code httpRequest}. 40 | *

41 | * The returned path corresponds to the target of the provided {@code httpRequest} without the requests 42 | * parameters. For example, calling this method on a request with the URI {@code /target?param=value} will return 43 | * {@code /target}. 44 | * 45 | * @param httpRequest the {@link HttpRequest} to get the path from 46 | * @return the path associated to the provided {@code httpRequest} 47 | * @throws URISyntaxException if the provided {@code httpRequest}'s URI is invalid 48 | */ 49 | public static String getPath(@Nonnull HttpRequest httpRequest) throws URISyntaxException { 50 | checkNotNull(httpRequest, "Cannot retrieve the path from the provided %s %s", 51 | HttpRequest.class.getSimpleName(), httpRequest); 52 | URIBuilder uriBuilder = getURIBuilderFrom(httpRequest); 53 | return uriBuilder.getPath(); 54 | } 55 | 56 | /** 57 | * Returns a {@link List} containing the parameters associated to the provided {@code httpRequest}. 58 | *

59 | * Calling this method on a {@code httpRequest} instance that does not define any parameter in its request URI 60 | * returns an empty {@link List}. 61 | * 62 | * @param httpRequest the {@link HttpRequest} to get the parameters from 63 | * @return a {@link List} containing the parameters associated to the provided {@code httpRequest} 64 | * @throws URISyntaxException if the provided {@code httpRequest}'s URI is invalid 65 | */ 66 | public static List getParameters(@Nonnull HttpRequest httpRequest) throws URISyntaxException { 67 | checkNotNull(httpRequest, "Cannot retrieve the parameters from the provided %s %s", 68 | HttpRequest.class.getSimpleName(), httpRequest); 69 | URIBuilder uriBuilder = getURIBuilderFrom(httpRequest); 70 | return uriBuilder.getQueryParams(); 71 | } 72 | 73 | /** 74 | * Returns the value associated to the provided {@code parameterName} from the given {@code parameters} list. 75 | * 76 | * @param parameterName the name of the parameter to retrieve the value of 77 | * @param parameters the list of parameters to search in 78 | * @return the value associated to the provided {@code parameterName} from the given {@code parameters} list 79 | */ 80 | public static @Nullable 81 | String getParameterValue(@Nonnull String parameterName, @Nonnull List parameters) { 82 | checkNotNull(parameterName, "Cannot retrieve the value of parameter %s", parameterName); 83 | checkNotNull(parameters, "Cannot retrieve parameters from the provided list: %s", parameters); 84 | return parameters.stream().filter(p -> p.getName().equals(parameterName)) 85 | .map(NameValuePair::getValue).findFirst().orElse(null); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/server/RestHandlerException.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.server; 2 | 3 | import org.apache.http.HttpStatus; 4 | 5 | /** 6 | * An exception thrown by {@link RestHandler}s to notify the {@link XatkitServer}. 7 | *

8 | * This exception is used to set the HTTP response's status code in the {@link XatkitServer}: by default the server 9 | * returns a status code {@code 200}, but it will return a {@code 404} if the {@link RestHandler} threw a 10 | * {@link RestHandlerException}. 11 | */ 12 | public class RestHandlerException extends Exception { 13 | 14 | /** 15 | * The HTTP error code associated to the exception. 16 | *

17 | * This error code defaults to {@link HttpStatus#SC_NOT_FOUND} when not provided ({@code 404}). 18 | */ 19 | private int errorCode; 20 | 21 | /** 22 | * Constructs a {@link RestHandlerException}. 23 | *

24 | * The {@code errorCode} of the created exception is set to {@link HttpStatus#SC_NOT_FOUND}. 25 | */ 26 | public RestHandlerException() { 27 | this(HttpStatus.SC_NOT_FOUND, "", null); 28 | } 29 | 30 | /** 31 | * Constructs a {@link RestHandlerException} with the provided HTTP {@code errorCode} and {@code message}. 32 | * 33 | * @param errorCode the HTTP error code 34 | * @param message the exception's message 35 | */ 36 | public RestHandlerException(int errorCode, String message) { 37 | this(errorCode, message, null); 38 | } 39 | 40 | /** 41 | * Constructs a {@link RestHandlerException} from the provided {@code message}. 42 | *

43 | * The {@code errorCode} of the created exception is set to {@link HttpStatus#SC_NOT_FOUND}. 44 | * 45 | * @param message the exception's message 46 | */ 47 | public RestHandlerException(String message) { 48 | this(HttpStatus.SC_NOT_FOUND, message, null); 49 | } 50 | 51 | /** 52 | * Constructs a {@link RestHandlerException} from the provided {@code message} and {@code cause}. 53 | *

54 | * The {@code errorCode} of the created exception is set to {@link HttpStatus#SC_NOT_FOUND}. 55 | * 56 | * @param message the exception's message 57 | * @param cause the exception's cause 58 | */ 59 | public RestHandlerException(String message, Throwable cause) { 60 | this(HttpStatus.SC_NOT_FOUND, message, cause); 61 | } 62 | 63 | /** 64 | * Constructs a {@link RestHandlerException} from the provided HTTP {@code errorCode}, {@code message}, and {@code 65 | * cause}. 66 | * 67 | * @param errorCode errorCode the HTTP error code 68 | * @param message the exception's message 69 | * @param cause the exception's cause 70 | */ 71 | public RestHandlerException(int errorCode, String message, Throwable cause) { 72 | super(message, cause); 73 | this.errorCode = errorCode; 74 | } 75 | 76 | /** 77 | * Constructs a {@link RestHandlerException} from the provided {@code cause}. 78 | *

79 | * The {@code errorCode} of the created exception is set to {@link HttpStatus#SC_NOT_FOUND}. 80 | * 81 | * @param cause the exception's cause 82 | */ 83 | public RestHandlerException(Throwable cause) { 84 | this(HttpStatus.SC_NOT_FOUND, "", cause); 85 | } 86 | 87 | /** 88 | * Constructs a {@link RestHandlerException} from the provided HTTP {@code errorCode} and {@code cause}. 89 | * 90 | * @param errorCode the HTTP error code 91 | * @param cause the exception's cause 92 | */ 93 | public RestHandlerException(int errorCode, Throwable cause) { 94 | this(HttpStatus.SC_NOT_FOUND, "", cause); 95 | } 96 | 97 | /** 98 | * Returns the HTTP error code associated to this exception. 99 | * 100 | * @return the HTTP error code associated to this exception 101 | */ 102 | public int getErrorCode() { 103 | return this.errorCode; 104 | } 105 | 106 | /** 107 | * Constructs a {@link RestHandlerException} from the provided {@code message}, {@code cause}, {@code 108 | * enableSuppression}, and {@code writeableStackTrace}. 109 | * 110 | * @param message the exception's message 111 | * @param cause the exception's cause 112 | * @param enableSuppression whether or not suppression is enabled 113 | * @param writeableStackTrace whether or not the stack trace should be writable 114 | */ 115 | protected RestHandlerException(String message, Throwable cause, boolean enableSuppression, 116 | boolean writeableStackTrace) { 117 | super(message, cause, enableSuppression, writeableStackTrace); 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/server/RestHandlerFactory.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.server; 2 | 3 | import com.google.gson.JsonElement; 4 | import org.apache.http.Header; 5 | import org.apache.http.NameValuePair; 6 | 7 | import javax.annotation.Nonnull; 8 | import javax.annotation.Nullable; 9 | import java.util.List; 10 | 11 | /** 12 | * A {@link RestHandler} factory providing utility methods to create specific {@link RestHandler} instances. 13 | */ 14 | public final class RestHandlerFactory { 15 | 16 | /** 17 | * Disables the default constructor, this class only provides static methods and should not be constructed. 18 | */ 19 | private RestHandlerFactory() { 20 | } 21 | 22 | /** 23 | * A functional interface representing the handling function of {@link JsonRestHandler}. 24 | */ 25 | @FunctionalInterface 26 | public interface JsonRestHandlerFunction { 27 | 28 | /** 29 | * The handling function of {@link JsonRestHandler}. 30 | *

31 | * This method has the same signature as {@link JsonRestHandler#handleParsedContent(List, List, JsonElement)} 32 | * , and can be used in {@link #createJsonRestHandler(JsonRestHandlerFunction)} to set its behavior. 33 | * 34 | * @param headers the HTTP headers of the received request 35 | * @param params the request parameters 36 | * @param content the {@link JsonElement} representing the content of the HTTP request 37 | * @return the {@link JsonElement} containing the endpoint response, or {@code null} 38 | * @throws RestHandlerException if an error occurred when handling the request 39 | * @see #createJsonRestHandler(JsonRestHandlerFunction) 40 | */ 41 | @Nullable 42 | JsonElement handle(@Nonnull List

headers, @Nonnull List params, 43 | @Nullable JsonElement content) throws RestHandlerException; 44 | } 45 | 46 | /** 47 | * A functional interface representing the handling function of {@link EmptyContentRestHandler}. 48 | */ 49 | @FunctionalInterface 50 | public interface EmptyContentRestHandlerFunction { 51 | 52 | /** 53 | * The handling function of {@link EmptyContentRestHandler}. 54 | *

55 | * This method has the same signature as 56 | * {@link EmptyContentRestHandler#handleParsedContent(List, List, Object)}, and can be used in 57 | * {@link #createEmptyContentRestHandler(EmptyContentRestHandlerFunction)} to set its behavior. 58 | * 59 | * @param headers the HTTP headers of the received request 60 | * @param params the request parameters 61 | * @param content {@code null} ({@link EmptyContentRestHandler} does not accept any request content) 62 | * @return the {@link Object} containing the endpoint result, or {@code null} 63 | * @throws RestHandlerException if an error occurred when handling the request 64 | */ 65 | @Nullable 66 | Object handle(@Nonnull List

headers, @Nonnull List params, 67 | @Nullable Object content) throws RestHandlerException; 68 | } 69 | 70 | /** 71 | * Creates a {@link JsonRestHandler} and sets its handling method with the provided {@code function}. 72 | * 73 | * @param function the {@link JsonRestHandlerFunction} used to define the handler behavior 74 | * @return the created {@link JsonRestHandler} 75 | */ 76 | public static JsonRestHandler createJsonRestHandler(final JsonRestHandlerFunction function) { 77 | return new JsonRestHandler() { 78 | @Nullable 79 | @Override 80 | public JsonElement handleParsedContent(@Nonnull List
headers, 81 | @Nonnull List params, 82 | @Nullable JsonElement content) throws RestHandlerException { 83 | return function.handle(headers, params, content); 84 | } 85 | }; 86 | } 87 | 88 | /** 89 | * Creates an {@link EmptyContentRestHandler} and sets its handling method with the provided {@code function}. 90 | * 91 | * @param function the {@link EmptyContentRestHandlerFunction} used to define the handler behavior 92 | * @return the created {@link EmptyContentRestHandler} 93 | */ 94 | public static EmptyContentRestHandler createEmptyContentRestHandler(final EmptyContentRestHandlerFunction function) { 95 | return new EmptyContentRestHandler() { 96 | @Nullable 97 | @Override 98 | protected Object handleParsedContent(@Nonnull List
headers, @Nonnull List params, 99 | @Nullable Object content) throws RestHandlerException { 100 | return function.handle(headers, params, content); 101 | } 102 | }; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/core/server/XatkitServerUtils.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.server; 2 | 3 | /** 4 | * Utility values for the {@link XatkitServer}. 5 | *

6 | * This interface contains the configuration keys and default values used by the {@link XatkitServer} and its 7 | * internal components. 8 | */ 9 | public interface XatkitServerUtils { 10 | 11 | /** 12 | * The configuration key to store the server port to use. 13 | */ 14 | String SERVER_PORT_KEY = "xatkit.server.port"; 15 | 16 | /** 17 | * The default port to use. 18 | *

19 | * The server port can be customized in the constructor's configuration using the {@link #SERVER_PORT_KEY} key. 20 | */ 21 | int DEFAULT_SERVER_PORT = 5000; 22 | 23 | /** 24 | * The configuration key used to specify the Xatkit server location (public URL). 25 | *

26 | * This key is used to customize HTML templates and Javascript to connect them to the running 27 | * {@link XatkitServer} instance. 28 | * 29 | * @see #DEFAULT_SERVER_LOCATION 30 | */ 31 | String SERVER_PUBLIC_URL_KEY = "xatkit.server.public_url"; 32 | 33 | /** 34 | * The default Xatkit server location. 35 | *

36 | * This value is used if the configuration does not contain a server public url, and allows to test bots in 37 | * a local development environment by connecting to {@code http://localhost:5000}. 38 | * 39 | * @see #SERVER_PUBLIC_URL_KEY 40 | */ 41 | String DEFAULT_SERVER_LOCATION = "http://localhost"; 42 | 43 | /** 44 | * The URL fragment used to access Xatkit public content. 45 | */ 46 | String PUBLIC_CONTENT_URL_FRAGMENT = "/content/"; 47 | 48 | /** 49 | * The directory name used to store Xatkit public content. 50 | */ 51 | String PUBLIC_DIRECTORY_NAME = "public"; 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/CompositeEntryFragmentStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity; 2 | 3 | import com.xatkit.intent.EntityDefinitionReference; 4 | import lombok.NonNull; 5 | 6 | public interface CompositeEntryFragmentStep extends CompositeEntryStep, CustomEntityDefinitionProvider { 7 | 8 | @NonNull CompositeEntryFragmentStep text(@NonNull String text); 9 | 10 | @NonNull CompositeEntryFragmentStep entity(@NonNull EntityDefinitionReferenceProvider entityReference); 11 | 12 | @NonNull CompositeEntryFragmentStep entity(@NonNull EntityDefinitionReference entityReference); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/CompositeEntryStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity; 2 | 3 | import lombok.NonNull; 4 | 5 | public interface CompositeEntryStep { 6 | 7 | @NonNull CompositeEntryFragmentStep entry(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/CustomEntityDefinitionProvider.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity; 2 | 3 | import com.xatkit.intent.CustomEntityDefinition; 4 | import lombok.NonNull; 5 | 6 | public interface CustomEntityDefinitionProvider { 7 | 8 | @NonNull CustomEntityDefinition getEntity(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/EntityDefinitionReferenceProvider.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity; 2 | 3 | import com.xatkit.intent.EntityDefinitionReference; 4 | import lombok.NonNull; 5 | 6 | public interface EntityDefinitionReferenceProvider { 7 | 8 | @NonNull EntityDefinitionReference getEntityReference(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/MappingEntryStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity; 2 | 3 | import lombok.NonNull; 4 | 5 | public interface MappingEntryStep { 6 | 7 | @NonNull MappingReferenceValueStep entry(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/MappingReferenceValueStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity; 2 | 3 | import lombok.NonNull; 4 | 5 | public interface MappingReferenceValueStep extends MappingEntryStep { 6 | 7 | @NonNull MappingSynonymStep value(@NonNull String referenceValue); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/MappingSynonymStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity; 2 | 3 | import lombok.NonNull; 4 | 5 | public interface MappingSynonymStep extends MappingEntryStep, CustomEntityDefinitionProvider, 6 | EntityDefinitionReferenceProvider { 7 | 8 | @NonNull MappingSynonymStep synonym(@NonNull String synonym); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/impl/CompositeEntityDefinitionBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity.impl; 2 | 3 | import com.xatkit.dsl.entity.CompositeEntryFragmentStep; 4 | import com.xatkit.dsl.entity.CompositeEntryStep; 5 | import com.xatkit.intent.CompositeEntityDefinition; 6 | import com.xatkit.intent.IntentFactory; 7 | import lombok.NonNull; 8 | 9 | public class CompositeEntityDefinitionBuilder extends CustomEntityDefinitionProviderImpl 10 | implements CompositeEntryStep { 11 | 12 | public CompositeEntityDefinitionBuilder() { 13 | this.entity = IntentFactory.eINSTANCE.createCompositeEntityDefinition(); 14 | } 15 | 16 | @Override 17 | public @NonNull CompositeEntryFragmentStep entry() { 18 | return new CompositeEntityDefinitionEntryBuilder(this.entity); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/impl/CompositeEntityDefinitionEntryBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity.impl; 2 | 3 | import com.xatkit.dsl.entity.CompositeEntryFragmentStep; 4 | import com.xatkit.dsl.entity.CustomEntityDefinitionProvider; 5 | import com.xatkit.dsl.entity.EntityDefinitionReferenceProvider; 6 | import com.xatkit.intent.CompositeEntityDefinition; 7 | import com.xatkit.intent.CompositeEntityDefinitionEntry; 8 | import com.xatkit.intent.EntityDefinitionReference; 9 | import com.xatkit.intent.EntityTextFragment; 10 | import com.xatkit.intent.IntentFactory; 11 | import com.xatkit.intent.LiteralTextFragment; 12 | import lombok.NonNull; 13 | 14 | public class CompositeEntityDefinitionEntryBuilder extends CompositeEntityDefinitionBuilder implements 15 | CompositeEntryFragmentStep, 16 | CustomEntityDefinitionProvider { 17 | 18 | private CompositeEntityDefinitionEntry entry; 19 | 20 | public CompositeEntityDefinitionEntryBuilder(CompositeEntityDefinition parent) { 21 | this.entity = parent; 22 | this.entry = IntentFactory.eINSTANCE.createCompositeEntityDefinitionEntry(); 23 | /* 24 | * Add the entry right now because we don't know what will be the last call to define it (we can have 25 | * multiple fragments in a composite entity entry). 26 | */ 27 | this.entity.getEntries().add(this.entry); 28 | } 29 | 30 | @Override 31 | public @NonNull CompositeEntryFragmentStep text(@NonNull String text) { 32 | LiteralTextFragment fragment = IntentFactory.eINSTANCE.createLiteralTextFragment(); 33 | fragment.setValue(text); 34 | this.entry.getFragments().add(fragment); 35 | return this; 36 | } 37 | 38 | @Override 39 | public @NonNull CompositeEntryFragmentStep entity(@NonNull EntityDefinitionReferenceProvider entityReference) { 40 | return this.entity(entityReference.getEntityReference()); 41 | } 42 | 43 | @Override 44 | public @NonNull CompositeEntryFragmentStep entity(@NonNull EntityDefinitionReference entityReference) { 45 | EntityTextFragment fragment = IntentFactory.eINSTANCE.createEntityTextFragment(); 46 | fragment.setEntityReference(entityReference); 47 | this.entry.getFragments().add(fragment); 48 | return this; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/impl/CustomEntityDefinitionProviderImpl.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity.impl; 2 | 3 | import com.xatkit.dsl.entity.CustomEntityDefinitionProvider; 4 | import com.xatkit.dsl.entity.EntityDefinitionReferenceProvider; 5 | import com.xatkit.intent.CustomEntityDefinition; 6 | import com.xatkit.intent.CustomEntityDefinitionReference; 7 | import com.xatkit.intent.EntityDefinitionReference; 8 | import com.xatkit.intent.IntentFactory; 9 | import lombok.NonNull; 10 | 11 | public class CustomEntityDefinitionProviderImpl implements 12 | CustomEntityDefinitionProvider, EntityDefinitionReferenceProvider { 13 | 14 | protected T entity; 15 | 16 | @Override 17 | public @NonNull T getEntity() { 18 | return this.entity; 19 | } 20 | 21 | public @NonNull CustomEntityDefinitionProviderImpl name(@NonNull String name) { 22 | this.entity.setName(name); 23 | return this; 24 | } 25 | 26 | @Override 27 | public @NonNull EntityDefinitionReference getEntityReference() { 28 | CustomEntityDefinitionReference reference = IntentFactory.eINSTANCE.createCustomEntityDefinitionReference(); 29 | reference.setCustomEntity(this.entity); 30 | return reference; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/impl/MappingEntityDefinitionBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity.impl; 2 | 3 | import com.xatkit.dsl.entity.MappingEntryStep; 4 | import com.xatkit.dsl.entity.MappingReferenceValueStep; 5 | import com.xatkit.intent.IntentFactory; 6 | import com.xatkit.intent.MappingEntityDefinition; 7 | import lombok.NonNull; 8 | 9 | public class MappingEntityDefinitionBuilder extends CustomEntityDefinitionProviderImpl 10 | implements MappingEntryStep { 11 | 12 | public MappingEntityDefinitionBuilder() { 13 | this.entity = IntentFactory.eINSTANCE.createMappingEntityDefinition(); 14 | } 15 | 16 | @Override 17 | public @NonNull MappingReferenceValueStep entry() { 18 | return new MappingEntityDefinitionEntryBuilder(this.entity); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/entity/impl/MappingEntityDefinitionEntryBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.entity.impl; 2 | 3 | import com.xatkit.dsl.entity.CustomEntityDefinitionProvider; 4 | import com.xatkit.dsl.entity.MappingReferenceValueStep; 5 | import com.xatkit.dsl.entity.MappingSynonymStep; 6 | import com.xatkit.intent.IntentFactory; 7 | import com.xatkit.intent.MappingEntityDefinition; 8 | import com.xatkit.intent.MappingEntityDefinitionEntry; 9 | import lombok.NonNull; 10 | 11 | // Wrapper? Delegate? 12 | public class MappingEntityDefinitionEntryBuilder extends MappingEntityDefinitionBuilder implements 13 | MappingReferenceValueStep, 14 | MappingSynonymStep, 15 | CustomEntityDefinitionProvider { 16 | 17 | private MappingEntityDefinitionEntry entry; 18 | 19 | public MappingEntityDefinitionEntryBuilder(MappingEntityDefinition parent) { 20 | this.entity = parent; 21 | this.entry = IntentFactory.eINSTANCE.createMappingEntityDefinitionEntry(); 22 | /* 23 | * Add the entry right now because we don't know what will be the last call to define it (we can have 24 | * multiple synonyms in an entry). 25 | */ 26 | this.entity.getEntries().add(this.entry); 27 | } 28 | 29 | @Override 30 | public @NonNull MappingSynonymStep value(@NonNull String referenceValue) { 31 | this.entry.setReferenceValue(referenceValue); 32 | return this; 33 | } 34 | 35 | @Override 36 | public @NonNull MappingSynonymStep synonym(@NonNull String synonym) { 37 | this.entry.getSynonyms().add(synonym); 38 | return this; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/EventContextParameterStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | import lombok.NonNull; 4 | 5 | public interface EventContextParameterStep extends EventDefinitionProvider { 6 | 7 | @NonNull EventContextParameterStep parameter(@NonNull String name); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/EventDefinitionProvider.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | import com.xatkit.intent.EventDefinition; 4 | import lombok.NonNull; 5 | 6 | public interface EventDefinitionProvider { 7 | 8 | @NonNull EventDefinition getEventDefinition(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/IntentContextLifespanStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | import lombok.NonNull; 4 | 5 | public interface IntentContextLifespanStep extends IntentContextParameterStep, EventDefinitionProvider { 6 | 7 | @NonNull IntentContextParameterStep lifespan(int lifespan); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/IntentContextParameterEntityStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | import com.xatkit.dsl.entity.EntityDefinitionReferenceProvider; 4 | import com.xatkit.intent.EntityDefinitionReference; 5 | import lombok.NonNull; 6 | 7 | public interface IntentContextParameterEntityStep extends IntentDefinitionProvider { 8 | 9 | @NonNull IntentContextParameterStep entity(@NonNull EntityDefinitionReferenceProvider entityReferenceProvider); 10 | 11 | @NonNull IntentContextParameterStep entity(@NonNull EntityDefinitionReference entityReference); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/IntentContextParameterFragmentStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | import lombok.NonNull; 4 | 5 | public interface IntentContextParameterFragmentStep extends IntentDefinitionProvider { 6 | 7 | @NonNull IntentContextParameterEntityStep fromFragment(@NonNull String fragment); 8 | 9 | @NonNull IntentContextParameterEntityStep fromFragment(@NonNull String... fragment); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/IntentContextParameterStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | import lombok.NonNull; 4 | 5 | public interface IntentContextParameterStep extends IntentDefinitionProvider { 6 | 7 | @NonNull IntentContextParameterFragmentStep parameter(@NonNull String parameterName); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/IntentDefinitionProvider.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | import com.xatkit.intent.IntentDefinition; 4 | import lombok.NonNull; 5 | 6 | public interface IntentDefinitionProvider extends EventDefinitionProvider { 7 | 8 | @NonNull IntentDefinition getIntentDefinition(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/IntentMandatoryTrainingSentenceStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | public interface IntentMandatoryTrainingSentenceStep extends IntentVar { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/IntentOptionalTrainingSentenceStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | public interface IntentOptionalTrainingSentenceStep extends 4 | IntentMandatoryTrainingSentenceStep, 5 | IntentContextParameterStep, 6 | IntentDefinitionProvider { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/IntentVar.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent; 2 | 3 | import lombok.NonNull; 4 | 5 | /** 6 | * Commodity interface (= IntentMandatoryTrainingSentence) to have clear usage of the DSL: 7 | * IntentVar myIntent = intent("MyState") 8 | */ 9 | public interface IntentVar extends IntentDefinitionProvider { 10 | 11 | @NonNull IntentOptionalTrainingSentenceStep trainingSentence(@NonNull String trainingSentence); 12 | 13 | @NonNull IntentOptionalTrainingSentenceStep trainingSentences(@NonNull Iterable trainingSentences); 14 | 15 | @NonNull IntentOptionalTrainingSentenceStep trainingSentences(@NonNull String[] trainingSentences); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/impl/EventDefinitionBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent.impl; 2 | 3 | import com.xatkit.dsl.intent.EventContextParameterStep; 4 | import com.xatkit.intent.ContextParameter; 5 | import com.xatkit.intent.IntentFactory; 6 | import lombok.NonNull; 7 | 8 | public class EventDefinitionBuilder extends EventDefinitionProviderImpl implements EventContextParameterStep { 9 | 10 | public EventDefinitionBuilder() { 11 | this.event = IntentFactory.eINSTANCE.createEventDefinition(); 12 | } 13 | 14 | public @NonNull EventDefinitionBuilder name(@NonNull String name) { 15 | this.event.setName(name); 16 | return this; 17 | } 18 | 19 | @Override 20 | public @NonNull EventContextParameterStep parameter(@NonNull String name) { 21 | ContextParameter contextParameter = IntentFactory.eINSTANCE.createContextParameter(); 22 | contextParameter.setName(name); 23 | this.event.getParameters().add(contextParameter); 24 | return this; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/impl/EventDefinitionProviderImpl.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent.impl; 2 | 3 | import com.xatkit.dsl.intent.EventDefinitionProvider; 4 | import com.xatkit.intent.EventDefinition; 5 | import lombok.NonNull; 6 | 7 | public class EventDefinitionProviderImpl implements EventDefinitionProvider { 8 | 9 | protected EventDefinition event; 10 | 11 | @Override 12 | public @NonNull EventDefinition getEventDefinition() { 13 | return this.event; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/impl/IntentContextParameterBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent.impl; 2 | 3 | import com.xatkit.dsl.entity.EntityDefinitionReferenceProvider; 4 | import com.xatkit.dsl.intent.IntentContextParameterEntityStep; 5 | import com.xatkit.dsl.intent.IntentContextParameterFragmentStep; 6 | import com.xatkit.dsl.intent.IntentContextParameterStep; 7 | import com.xatkit.intent.ContextParameter; 8 | import com.xatkit.intent.EntityDefinitionReference; 9 | import com.xatkit.intent.IntentDefinition; 10 | import com.xatkit.intent.IntentFactory; 11 | import lombok.NonNull; 12 | 13 | import java.util.Arrays; 14 | 15 | public class IntentContextParameterBuilder extends IntentDefinitionProviderImpl implements 16 | IntentContextParameterFragmentStep, 17 | IntentContextParameterEntityStep, 18 | IntentContextParameterStep { 19 | 20 | private ContextParameter parameter; 21 | 22 | public IntentContextParameterBuilder(@NonNull IntentDefinition parentIntent) { 23 | this.intent = parentIntent; 24 | this.parameter = IntentFactory.eINSTANCE.createContextParameter(); 25 | } 26 | 27 | public @NonNull IntentContextParameterBuilder name(@NonNull String name) { 28 | this.parameter.setName(name); 29 | return this; 30 | } 31 | 32 | @Override 33 | public @NonNull IntentContextParameterStep entity(@NonNull EntityDefinitionReferenceProvider entityReference) { 34 | return this.entity(entityReference.getEntityReference()); 35 | } 36 | 37 | @Override 38 | public @NonNull IntentContextParameterStep entity(@NonNull EntityDefinitionReference entityReference) { 39 | this.parameter.setEntity(entityReference); 40 | this.intent.getParameters().add(this.parameter); 41 | return this; 42 | } 43 | 44 | @Override 45 | public @NonNull IntentContextParameterEntityStep fromFragment(@NonNull String fragment) { 46 | this.parameter.getTextFragments().add(fragment); 47 | return this; 48 | } 49 | 50 | @Override 51 | public @NonNull IntentContextParameterEntityStep fromFragment(@NonNull String... fragment) { 52 | this.parameter.getTextFragments().addAll(Arrays.asList(fragment)); 53 | return this; 54 | } 55 | 56 | @Override 57 | public @NonNull IntentContextParameterFragmentStep parameter(@NonNull String parameterName) { 58 | // Second parameter 59 | // TODO update this comment or delete it 60 | IntentContextParameterBuilder intentContextParameterBuilder = new IntentContextParameterBuilder(this.intent); 61 | intentContextParameterBuilder.name(parameterName); 62 | return intentContextParameterBuilder; 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/impl/IntentDefinitionBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent.impl; 2 | 3 | import com.xatkit.dsl.intent.IntentContextParameterFragmentStep; 4 | import com.xatkit.dsl.intent.IntentMandatoryTrainingSentenceStep; 5 | import com.xatkit.dsl.intent.IntentOptionalTrainingSentenceStep; 6 | import com.xatkit.intent.IntentFactory; 7 | import lombok.NonNull; 8 | 9 | import java.util.Arrays; 10 | 11 | public class IntentDefinitionBuilder extends IntentDefinitionProviderImpl implements 12 | IntentMandatoryTrainingSentenceStep, 13 | IntentOptionalTrainingSentenceStep { 14 | 15 | public IntentDefinitionBuilder() { 16 | this.intent = IntentFactory.eINSTANCE.createIntentDefinition(); 17 | } 18 | 19 | public @NonNull IntentDefinitionBuilder name(@NonNull String name) { 20 | this.intent.setName(name); 21 | return this; 22 | } 23 | 24 | @Override 25 | public @NonNull IntentContextParameterFragmentStep parameter(@NonNull String parameterName) { 26 | IntentContextParameterBuilder intentContextParameterBuilder = new IntentContextParameterBuilder(this.intent); 27 | intentContextParameterBuilder.name(parameterName); 28 | return intentContextParameterBuilder; 29 | } 30 | 31 | @Override 32 | public @NonNull IntentOptionalTrainingSentenceStep trainingSentence(@NonNull String trainingSentence) { 33 | this.intent.getTrainingSentences().add(trainingSentence); 34 | return this; 35 | } 36 | 37 | @Override 38 | public @NonNull IntentOptionalTrainingSentenceStep trainingSentences(@NonNull Iterable trainingSentences) { 39 | trainingSentences.forEach(this::trainingSentence); 40 | return this; 41 | } 42 | 43 | @Override 44 | public @NonNull IntentOptionalTrainingSentenceStep trainingSentences(@NonNull String[] trainingSentences) { 45 | return this.trainingSentences(Arrays.asList(trainingSentences)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/intent/impl/IntentDefinitionProviderImpl.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.intent.impl; 2 | 3 | import com.xatkit.dsl.intent.IntentDefinitionProvider; 4 | import com.xatkit.intent.EventDefinition; 5 | import com.xatkit.intent.IntentDefinition; 6 | import lombok.NonNull; 7 | 8 | public class IntentDefinitionProviderImpl extends EventDefinitionProviderImpl implements IntentDefinitionProvider { 9 | 10 | protected IntentDefinition intent; 11 | 12 | @Override 13 | public @NonNull IntentDefinition getIntentDefinition() { 14 | return this.intent; 15 | } 16 | 17 | @Override 18 | public @NonNull EventDefinition getEventDefinition() { 19 | return this.getIntentDefinition(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/library/EntityStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.library; 2 | 3 | import com.xatkit.dsl.entity.CustomEntityDefinitionProvider; 4 | import lombok.NonNull; 5 | 6 | public interface EntityStep extends IntentStep { 7 | 8 | @NonNull EntityStep entity(@NonNull CustomEntityDefinitionProvider entityProvider); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/library/IntentStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.library; 2 | 3 | import com.xatkit.dsl.intent.IntentDefinitionProvider; 4 | import lombok.NonNull; 5 | 6 | public interface IntentStep extends LibraryProvider { 7 | 8 | @NonNull IntentStep intent(@NonNull IntentDefinitionProvider intentProvider); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/library/LibraryProvider.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.library; 2 | 3 | import com.xatkit.intent.Library; 4 | import lombok.NonNull; 5 | 6 | public interface LibraryProvider { 7 | 8 | @NonNull Library getLibrary(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/library/impl/LibraryBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.library.impl; 2 | 3 | import com.xatkit.dsl.entity.CustomEntityDefinitionProvider; 4 | import com.xatkit.dsl.intent.IntentDefinitionProvider; 5 | import com.xatkit.dsl.library.EntityStep; 6 | import com.xatkit.dsl.library.IntentStep; 7 | import com.xatkit.intent.IntentFactory; 8 | import lombok.NonNull; 9 | 10 | public class LibraryBuilder extends LibraryProviderImpl implements EntityStep, IntentStep { 11 | 12 | public LibraryBuilder() { 13 | this.library = IntentFactory.eINSTANCE.createLibrary(); 14 | } 15 | 16 | public @NonNull LibraryBuilder name(@NonNull String name) { 17 | this.library.setName(name); 18 | return this; 19 | } 20 | 21 | @Override 22 | public @NonNull EntityStep entity(@NonNull CustomEntityDefinitionProvider entityProvider) { 23 | this.library.getCustomEntities().add(entityProvider.getEntity()); 24 | return this; 25 | } 26 | 27 | @Override 28 | public @NonNull IntentStep intent(@NonNull IntentDefinitionProvider intentProvider) { 29 | this.library.getEventDefinitions().add(intentProvider.getIntentDefinition()); 30 | return this; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/library/impl/LibraryProviderImpl.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.library.impl; 2 | 3 | import com.xatkit.dsl.library.LibraryProvider; 4 | import com.xatkit.intent.Library; 5 | import lombok.NonNull; 6 | 7 | public class LibraryProviderImpl implements LibraryProvider { 8 | 9 | protected Library library; 10 | 11 | @Override 12 | public @NonNull Library getLibrary() { 13 | return this.library; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/model/DefaultFallbackStateStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.model; 2 | 3 | import com.xatkit.dsl.state.StateProvider; 4 | import com.xatkit.execution.State; 5 | import lombok.NonNull; 6 | 7 | public interface DefaultFallbackStateStep { 8 | 9 | @NonNull ExecutionModelProvider defaultFallbackState(@NonNull StateProvider stateProvider); 10 | 11 | @NonNull ExecutionModelProvider defaultFallbackState(@NonNull State state); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/model/ExecutionModelProvider.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.model; 2 | 3 | import com.xatkit.execution.ExecutionModel; 4 | import lombok.NonNull; 5 | 6 | public interface ExecutionModelProvider { 7 | 8 | @NonNull ExecutionModel getExecutionModel(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/model/InitStateStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.model; 2 | 3 | import com.xatkit.dsl.state.StateProvider; 4 | import com.xatkit.execution.State; 5 | import lombok.NonNull; 6 | 7 | public interface InitStateStep { 8 | 9 | @NonNull DefaultFallbackStateStep initState(@NonNull StateProvider stateProvider); 10 | 11 | @NonNull DefaultFallbackStateStep initState(@NonNull State state); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/model/ListenToStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.model; 2 | 3 | import com.xatkit.core.platform.io.RuntimeEventProvider; 4 | import lombok.NonNull; 5 | 6 | public interface ListenToStep { //extends StateStep { 7 | 8 | @NonNull StateStep listenTo(@NonNull RuntimeEventProvider provider); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/model/StateStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.model; 2 | 3 | import com.xatkit.dsl.state.StateProvider; 4 | import lombok.NonNull; 5 | 6 | public interface StateStep extends InitStateStep, ListenToStep { 7 | 8 | @Deprecated 9 | @NonNull StateStep useState(@NonNull StateProvider stateProvider); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/model/UseEventStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.model; 2 | 3 | import com.xatkit.dsl.intent.EventDefinitionProvider; 4 | import com.xatkit.dsl.intent.IntentDefinitionProvider; 5 | import com.xatkit.dsl.library.LibraryProvider; 6 | import com.xatkit.intent.EventDefinition; 7 | import com.xatkit.intent.IntentDefinition; 8 | import com.xatkit.intent.Library; 9 | import lombok.NonNull; 10 | 11 | public interface UseEventStep extends UsePlatformStep { 12 | 13 | @Deprecated 14 | @NonNull UseEventStep useEvent(@NonNull EventDefinitionProvider eventProvider); 15 | 16 | @Deprecated 17 | @NonNull UseEventStep useEvent(@NonNull EventDefinition event); 18 | 19 | @Deprecated 20 | @NonNull UseEventStep useIntent(@NonNull IntentDefinitionProvider intentProvider); 21 | 22 | @Deprecated 23 | @NonNull UseEventStep useIntent(@NonNull IntentDefinition intent); 24 | 25 | @Deprecated 26 | @NonNull UseEventStep useIntents(@NonNull LibraryProvider libraryProvider); 27 | 28 | @Deprecated 29 | @NonNull UseEventStep useIntents(@NonNull Library library); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/model/UsePlatformStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.model; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import lombok.NonNull; 5 | 6 | public interface UsePlatformStep extends ListenToStep { 7 | 8 | @NonNull UsePlatformStep usePlatform(@NonNull RuntimePlatform platform); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/model/impl/ExecutionModelBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.model.impl; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.core.platform.io.RuntimeEventProvider; 5 | import com.xatkit.dsl.intent.EventDefinitionProvider; 6 | import com.xatkit.dsl.intent.IntentDefinitionProvider; 7 | import com.xatkit.dsl.library.LibraryProvider; 8 | import com.xatkit.dsl.model.DefaultFallbackStateStep; 9 | import com.xatkit.dsl.model.ExecutionModelProvider; 10 | import com.xatkit.dsl.model.InitStateStep; 11 | import com.xatkit.dsl.model.ListenToStep; 12 | import com.xatkit.dsl.model.StateStep; 13 | import com.xatkit.dsl.model.UseEventStep; 14 | import com.xatkit.dsl.model.UsePlatformStep; 15 | import com.xatkit.dsl.state.StateProvider; 16 | import com.xatkit.execution.ExecutionFactory; 17 | import com.xatkit.execution.State; 18 | import com.xatkit.intent.EventDefinition; 19 | import com.xatkit.intent.IntentDefinition; 20 | import com.xatkit.intent.Library; 21 | import lombok.NonNull; 22 | 23 | public class ExecutionModelBuilder extends ExecutionModelProviderImpl implements 24 | UseEventStep, 25 | UsePlatformStep, 26 | ListenToStep, 27 | StateStep, 28 | InitStateStep, 29 | DefaultFallbackStateStep { 30 | 31 | public ExecutionModelBuilder() { 32 | this.model = ExecutionFactory.eINSTANCE.createExecutionModel(); 33 | } 34 | 35 | 36 | @Deprecated 37 | @Override 38 | public @NonNull UseEventStep useEvent(@NonNull EventDefinitionProvider eventProvider) { 39 | return this.useEvent(eventProvider.getEventDefinition()); 40 | } 41 | 42 | @Deprecated 43 | @Override 44 | public @NonNull UseEventStep useEvent(@NonNull EventDefinition event) { 45 | this.model.getUsedEvents().add(event); 46 | return this; 47 | } 48 | 49 | @Deprecated 50 | @Override 51 | public @NonNull UseEventStep useIntent(@NonNull IntentDefinitionProvider intentProvider) { 52 | return this.useEvent(intentProvider); 53 | } 54 | 55 | @Deprecated 56 | @Override 57 | public @NonNull UseEventStep useIntent(@NonNull IntentDefinition intent) { 58 | return this.useEvent(intent); 59 | } 60 | 61 | @Deprecated 62 | @Override 63 | public @NonNull UseEventStep useIntents(@NonNull LibraryProvider libraryProvider) { 64 | return this.useIntents(libraryProvider.getLibrary()); 65 | } 66 | 67 | @Deprecated 68 | @Override 69 | public @NonNull UseEventStep useIntents(@NonNull Library library) { 70 | library.getEventDefinitions().forEach(e -> this.model.getUsedEvents().add(e)); 71 | return this; 72 | } 73 | 74 | @Override 75 | public @NonNull UsePlatformStep usePlatform(@NonNull RuntimePlatform platform) { 76 | this.model.getUsedPlatforms().add(platform); 77 | return this; 78 | } 79 | 80 | @Override 81 | public @NonNull StateStep listenTo(@NonNull RuntimeEventProvider provider) { 82 | this.model.getUsedProviders().add(provider); 83 | return this; 84 | } 85 | 86 | @Deprecated 87 | @Override 88 | public @NonNull StateStep useState(@NonNull StateProvider stateProvider) { 89 | this.model.getStates().add(stateProvider.getState()); 90 | return this; 91 | } 92 | 93 | @Override 94 | public @NonNull DefaultFallbackStateStep initState(@NonNull StateProvider stateProvider) { 95 | return this.initState(stateProvider.getState()); 96 | } 97 | 98 | @Override 99 | public @NonNull DefaultFallbackStateStep initState(@NonNull State state) { 100 | // TODO document that the state is added if it is not part of the specified states 101 | if (!this.model.getStates().contains(state)) { 102 | this.model.getStates().add(state); 103 | } 104 | this.model.setInitState(state); 105 | return this; 106 | } 107 | 108 | @Override 109 | public @NonNull ExecutionModelProvider defaultFallbackState(@NonNull StateProvider stateProvider) { 110 | return this.defaultFallbackState(stateProvider.getState()); 111 | } 112 | 113 | @Override 114 | public @NonNull ExecutionModelProvider defaultFallbackState(@NonNull State state) { 115 | // TODO document that the state is added if it is not part of the specified states 116 | if (!this.model.getStates().contains(state)) { 117 | this.model.getStates().add(state); 118 | } 119 | this.model.setDefaultFallbackState(state); 120 | return this; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/model/impl/ExecutionModelProviderImpl.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.model.impl; 2 | 3 | import com.xatkit.dsl.model.ExecutionModelProvider; 4 | import com.xatkit.execution.ExecutionModel; 5 | import lombok.NonNull; 6 | 7 | public class ExecutionModelProviderImpl implements ExecutionModelProvider { 8 | 9 | protected ExecutionModel model; 10 | 11 | @Override 12 | public @NonNull ExecutionModel getExecutionModel() { 13 | return this.model; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/BodyStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | public interface BodyStep extends NextStep, StateProvider, StateVar { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/EventPredicateStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | import com.xatkit.dsl.intent.EventDefinitionProvider; 4 | import com.xatkit.dsl.intent.IntentDefinitionProvider; 5 | import com.xatkit.intent.EventDefinition; 6 | import com.xatkit.intent.IntentDefinition; 7 | 8 | public interface EventPredicateStep { 9 | 10 | MoveToStep intentIs(IntentDefinitionProvider intentDefinitionProvider); 11 | 12 | MoveToStep intentIs(IntentDefinition intentDefinition); 13 | 14 | MoveToStep eventIs(EventDefinitionProvider eventDefinitionProvider); 15 | 16 | MoveToStep eventIs(EventDefinition eventDefinition); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/FallbackBodyStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | import com.xatkit.execution.StateContext; 4 | 5 | import java.util.function.Consumer; 6 | 7 | public interface FallbackBodyStep extends StateProvider { 8 | 9 | StateProvider body(Consumer body); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/FallbackStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | import com.xatkit.execution.StateContext; 4 | 5 | import java.util.function.Consumer; 6 | 7 | public interface FallbackStep extends StateProvider { 8 | 9 | StateProvider fallback(Consumer fallback); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/MoveToStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | import com.xatkit.execution.State; 4 | 5 | public interface MoveToStep extends StateProvider { 6 | 7 | OptionalWhenStep moveTo(StateProvider stateProvider); 8 | 9 | OptionalWhenStep moveTo(State state); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/NameStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | public interface NameStep extends StateProvider { 4 | 5 | BodyStep name(String name); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/NextStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | // TODO check if this is a state provider 4 | public interface NextStep extends StateProvider { 5 | 6 | TransitionStep next(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/OptionalWhenStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | public interface OptionalWhenStep extends WhenStep, FallbackStep { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/StateProvider.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | import com.xatkit.execution.State; 4 | 5 | /* 6 | * This should be moved at the mm level to ensure interoperability between languages. 7 | */ 8 | public interface StateProvider { 9 | 10 | State getState(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/StateVar.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | import com.xatkit.execution.StateContext; 4 | 5 | import java.util.function.Consumer; 6 | 7 | /** 8 | * Commodity interface (= BodyStep) to have clear usage of the DSL: 9 | * StateVar myState = state("MyState") 10 | */ 11 | public interface StateVar extends NextStep { 12 | 13 | NextStep body(Consumer body); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/TransitionStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | import com.xatkit.execution.State; 4 | 5 | public interface TransitionStep extends WhenStep, StateProvider { 6 | 7 | // MoveToStep when(Predicate condition); 8 | // Return state provider here because we don't want to allow fallback 9 | StateProvider moveTo(StateProvider stateProvider); 10 | 11 | StateProvider moveTo(State state); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/WhenStep.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state; 2 | 3 | import com.xatkit.execution.StateContext; 4 | 5 | import java.util.function.Predicate; 6 | 7 | public interface WhenStep extends StateProvider { 8 | 9 | MoveToStep when(Predicate condition); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/impl/StateBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state.impl; 2 | 3 | import com.xatkit.dsl.state.BodyStep; 4 | import com.xatkit.dsl.state.FallbackBodyStep; 5 | import com.xatkit.dsl.state.FallbackStep; 6 | import com.xatkit.dsl.state.NextStep; 7 | import com.xatkit.dsl.state.StateProvider; 8 | import com.xatkit.dsl.state.TransitionStep; 9 | import com.xatkit.execution.ExecutionFactory; 10 | import com.xatkit.execution.StateContext; 11 | import lombok.NonNull; 12 | 13 | import java.util.function.Consumer; 14 | 15 | public class StateBuilder extends StateProviderImpl implements 16 | BodyStep, 17 | FallbackBodyStep, 18 | NextStep, 19 | FallbackStep { 20 | 21 | public StateBuilder() { 22 | this.state = ExecutionFactory.eINSTANCE.createState(); 23 | } 24 | 25 | public @NonNull StateBuilder name(@NonNull String name) { 26 | this.state.setName(name); 27 | return this; 28 | } 29 | 30 | @Override 31 | public @NonNull NextStep body(@NonNull Consumer body) { 32 | this.state.setBody(body); 33 | return this; 34 | } 35 | 36 | @Override 37 | public @NonNull TransitionStep next() { 38 | return new TransitionBuilder(this.state); 39 | } 40 | 41 | @Override 42 | public @NonNull StateProvider fallback(@NonNull Consumer fallback) { 43 | this.state.setFallback(fallback); 44 | return this; 45 | } 46 | 47 | 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/impl/StateProviderImpl.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state.impl; 2 | 3 | import com.xatkit.dsl.state.StateProvider; 4 | import com.xatkit.execution.State; 5 | import lombok.NonNull; 6 | 7 | public class StateProviderImpl implements StateProvider { 8 | 9 | protected State state; 10 | 11 | @Override 12 | public @NonNull State getState() { 13 | return state; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/dsl/state/impl/TransitionBuilder.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl.state.impl; 2 | 3 | import com.xatkit.dsl.state.MoveToStep; 4 | import com.xatkit.dsl.state.OptionalWhenStep; 5 | import com.xatkit.dsl.state.StateProvider; 6 | import com.xatkit.dsl.state.TransitionStep; 7 | import com.xatkit.dsl.state.WhenStep; 8 | import com.xatkit.execution.ExecutionFactory; 9 | import com.xatkit.execution.GuardedTransition; 10 | import com.xatkit.execution.State; 11 | import com.xatkit.execution.StateContext; 12 | import com.xatkit.execution.Transition; 13 | import lombok.NonNull; 14 | 15 | import java.util.function.Predicate; 16 | 17 | import static java.util.Objects.isNull; 18 | 19 | public class TransitionBuilder extends StateBuilder implements 20 | TransitionStep, 21 | WhenStep, 22 | OptionalWhenStep, 23 | MoveToStep { 24 | 25 | private Transition transition; 26 | 27 | public TransitionBuilder(@NonNull State parent) { 28 | this.state = parent; 29 | } 30 | 31 | @Override 32 | public OptionalWhenStep moveTo(@NonNull StateProvider stateProvider) { 33 | return this.moveTo(stateProvider.getState()); 34 | } 35 | 36 | @Override 37 | public OptionalWhenStep moveTo(@NonNull State state) { 38 | if (isNull(this.transition)) { 39 | /* 40 | * The delegate didn't create a transition from a previous call, we are defining an AutoTransition. 41 | */ 42 | this.transition = ExecutionFactory.eINSTANCE.createAutoTransition(); 43 | } 44 | this.transition.setState(state); 45 | /* 46 | * Add the transition we are building to the parent state (we know it is complete at this point). 47 | */ 48 | this.state.getTransitions().add(this.transition); 49 | return this; 50 | } 51 | 52 | @Override 53 | public @NonNull MoveToStep when(@NonNull Predicate condition) { 54 | if (isNull(this.transition)) { 55 | GuardedTransition guardedTransition = ExecutionFactory.eINSTANCE.createGuardedTransition(); 56 | guardedTransition.setCondition(condition); 57 | this.transition = guardedTransition; 58 | return this; 59 | } else { 60 | /* 61 | * The current transition already contains a "moveTo" state. This invocation of when() means that we are 62 | * creating another transition: 63 | * next() 64 | * .when(...).moveTo(...) 65 | * .when() // Here we are defining a new transition. 66 | * We need to create and return a new builder to reflect this behavior. 67 | */ 68 | return new TransitionBuilder(this.state).when(condition); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/i18n/XatkitI18nHelper.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.i18n; 2 | 3 | import lombok.NonNull; 4 | 5 | import java.util.Locale; 6 | import java.util.ResourceBundle; 7 | 8 | /** 9 | * An utility class that wraps a {@link ResourceBundle} and allows to load {@link String} arrays from property files. 10 | *

11 | * This class provides an implementation of {@link #getStringArray(String)} that splits the result of 12 | * {@link #getString(String)} to return an {@link String} array. This is not possible with the default implementation 13 | * of {@link ResourceBundle} that doesn't contain a String-to-array transformation and throws a 14 | * {@link ClassCastException}. 15 | *

16 | * The {@link #getStringArray(String)} result is computed on the fly from the underlying {@link ResourceBundle} 17 | * contents. This means that you can provide an arbitrary number of {@link String} for each locale. 18 | * This is useful when translating intents where several (or none) translations can be provided for a given training 19 | * sentence. 20 | *

21 | * As an example, this class can be used to load localized intent training sentences: 22 | *

23 |  * {@code
24 |  * XatkitI18nHelper helper = new Xatkit18nHelper("MyIntentLibrary", Locale.FRENCH);
25 |  * val myIntent = intent("MyIntent")
26 |  *     .trainingSentences(helper.getStringArray("MyIntent"))
27 |  * }
28 |  * 
29 | *

30 | * Note: this class does not extend {@link ResourceBundle} because it is not designed to be loaded with different 31 | * locales. The concrete bundle is used internally to retrieve the localized values. 32 | */ 33 | public class XatkitI18nHelper { 34 | 35 | /** 36 | * The {@link ResourceBundle} used to access localized resources. 37 | */ 38 | private ResourceBundle bundle; 39 | 40 | /** 41 | * Constructs an instance of this class for the given resource {@code baseName} and the given {@code locale}. 42 | * 43 | * @param baseName the name of the {@link ResourceBundle} to use to retrieve localized resources 44 | * @param locale the {@link Locale} to use 45 | * @throws java.util.MissingResourceException if no resource bundle for the given {@code baseName} can be found 46 | */ 47 | public XatkitI18nHelper(String baseName, Locale locale) { 48 | this.bundle = ResourceBundle.getBundle(baseName, locale); 49 | } 50 | 51 | /** 52 | * Gets a {@link String} for the given {@code key} from the underlying bundle. 53 | * 54 | * @param key the key to retrieve the {@link String} for 55 | * @return the corresponding {@link String} if it exists, or {@code null} otherwise 56 | * @throws NullPointerException if the provided {@code key} is {@code null} 57 | * @throws java.util.MissingResourceException if no value for the given {@code key} can be found 58 | * @see ResourceBundle#getString(String) 59 | */ 60 | public @NonNull 61 | String getString(@NonNull String key) { 62 | return this.bundle.getString(key); 63 | } 64 | 65 | 66 | /** 67 | * Gets a {@link String} array for the given {@code key} from the underlying bundle. 68 | *

69 | * This method splits the {@link String} associated to the provided {@code key} to return an array. The delimiter 70 | * used to split the {@link String} is {@code \n}. 71 | * 72 | * @param key the key to retrieve the {@link String} for 73 | * @return the corresponding {@link String} array if it exists, {@code null} otherwise 74 | * @throws NullPointerException if the provided {@code key} is {@code null} 75 | * @throws java.util.MissingResourceException if no value for the given {@code key} can be found 76 | * @see ResourceBundle#getStringArray(String) 77 | */ 78 | public @NonNull 79 | String[] getStringArray(@NonNull String key) { 80 | return this.bundle.getString(key).split("\\n"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/platform/core/CorePlatform.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.platform.core; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | 5 | public class CorePlatform extends RuntimePlatform { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/platform/core/CoreUtils.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.platform.core; 2 | 3 | /** 4 | * An utility interface that holds Core-related properties. 5 | */ 6 | public interface CoreUtils { 7 | 8 | /** 9 | * The {@link org.apache.commons.configuration2.Configuration} key to specify the date/time when the 10 | * {@link com.xatkit.platform.core.io.CronEventProvider} should start generating {@code CronTick} events. 11 | *

12 | * Note: the starting date/time must follow the ISO_DATE_TIME format (it should be parsable 13 | * by {@link java.time.format.DateTimeFormatter#ISO_DATE_TIME}. 14 | */ 15 | String CRON_START_ON_KEY = "xatkit.core.cron.start_on"; 16 | 17 | /** 18 | * The {@link org.apache.commons.configuration2.Configuration} key to specify the interval between two {@code 19 | * CronTick} event generation (in seconds). 20 | *

21 | * The precision of the period is {@code 1} second, meaning that {@code CronTick} events can not be generated 22 | * faster than 1/second 23 | */ 24 | String CRON_PERIOD_KEY = "xatkit.core.cron.period"; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/util/EMFUtils.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.util; 2 | 3 | import org.eclipse.emf.ecore.EAttribute; 4 | import org.eclipse.emf.ecore.EObject; 5 | import org.eclipse.emf.ecore.EStructuralFeature; 6 | 7 | /** 8 | * An utility class providing helpers for EMF objects. 9 | */ 10 | public class EMFUtils { 11 | 12 | /** 13 | * Disables the default constructor, this class only provides static methods and should not be constructed. 14 | */ 15 | private EMFUtils() { } 16 | 17 | /** 18 | * Computes the name of the provided {@code eObject}. 19 | *

20 | * This method searches for a name attribute associated to the provided {@code eObject} and returns its 21 | * value. If there is no such attribute the value of the {@code toString()} method is returned. 22 | * 23 | * @param eObject the {@link EObject} to retrieve the name of 24 | * @return the name of the {@link EObject} 25 | */ 26 | public static String getName(EObject eObject) { 27 | EStructuralFeature feature = eObject.eClass().getEStructuralFeature("name"); 28 | if (feature instanceof EAttribute) { 29 | if (((EAttribute) feature).getEAttributeType().getInstanceClass().equals(String.class)) { 30 | return (String) eObject.eGet(feature); 31 | } 32 | } 33 | return eObject.toString(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/util/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.util; 2 | 3 | import com.xatkit.core.XatkitBot; 4 | import org.apache.commons.configuration2.Configuration; 5 | 6 | import java.io.File; 7 | import java.io.FileNotFoundException; 8 | import java.text.MessageFormat; 9 | 10 | import static java.util.Objects.isNull; 11 | 12 | /** 13 | * Utility methods to load Xatkit-related files. 14 | */ 15 | public final class FileUtils { 16 | 17 | /** 18 | * Disables the default constructor, this class only provides static methods and should not be constructed. 19 | */ 20 | private FileUtils() { 21 | } 22 | 23 | /** 24 | * Retrieves the {@link File} corresponding to the provided {@code path}. 25 | *

26 | * This method supports absolute and relative paths. Relative path are resolved against the configuration 27 | * directory (see {@link XatkitBot#CONFIGURATION_FOLDER_PATH_KEY}). If this directory is not specified then the 28 | * execution directory is used to resolve relative paths. 29 | * 30 | * @param path the path of the {@link File} to retrieve 31 | * @param configuration the Xatkit {@link Configuration} 32 | * @return the retrieved {@link File} 33 | */ 34 | public static File getFile(String path, Configuration configuration) { 35 | File file = new File(path); 36 | if (file.isAbsolute() || path.charAt(0) == '/') { 37 | /* 38 | * '/' comparison is a quickfix for windows, see https://bugs.openjdk.java.net/browse/JDK-8130462 39 | */ 40 | return file; 41 | } else { 42 | String relativePath = path; 43 | String configurationDirectoryPath = configuration.getString(XatkitBot.CONFIGURATION_FOLDER_PATH_KEY, ""); 44 | if (!configurationDirectoryPath.isEmpty()) { 45 | relativePath = configurationDirectoryPath + File.separator + path; 46 | } 47 | return new File(relativePath); 48 | } 49 | } 50 | 51 | /** 52 | * Returns the Xatkit installation directory. 53 | *

54 | * This method looks for the directory location stored in the {@code XATKIT} environment variable. If the 55 | * directory does not exist a {@link FileNotFoundException} is thrown. 56 | *

57 | * {@code XATKIT} environment variable can be set following this tutorial: https://github 58 | * .com/xatkit-bot-platform/xatkit-releases/wiki/Installation. 59 | * 60 | * @return the Xatkit installation directory 61 | * @throws FileNotFoundException if the Xatkit installation directory does not exist 62 | */ 63 | public static File getXatkitDirectory() throws FileNotFoundException { 64 | String xatkitDirectoryPath = System.getenv("XATKIT"); 65 | if (isNull(xatkitDirectoryPath) || xatkitDirectoryPath.isEmpty()) { 66 | throw new FileNotFoundException("Cannot find the Xatkit installation directory, please check this " 67 | + "tutorial article to see how to install Xatkit: https://github" 68 | + ".com/xatkit-bot-platform/xatkit-releases/wiki/Installation"); 69 | } 70 | File xatkitDirectoryFile = new File(xatkitDirectoryPath); 71 | if (!xatkitDirectoryFile.exists()) { 72 | throw new FileNotFoundException(MessageFormat.format("Cannot find the Xatkit installation directory ({0})" 73 | + ", please check this tutorial article to see how to install Xatkit: https://github" 74 | + ".com/xatkit-bot-platform/xatkit-releases/wiki/Installation", xatkitDirectoryPath)); 75 | } 76 | return xatkitDirectoryFile; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/util/IntentUtils.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.util; 2 | 3 | import com.xatkit.intent.BaseEntityDefinition; 4 | import com.xatkit.intent.ContextParameter; 5 | import com.xatkit.intent.EntityType; 6 | import com.xatkit.intent.IntentDefinition; 7 | import lombok.NonNull; 8 | 9 | import static fr.inria.atlanmod.commons.Preconditions.checkArgument; 10 | 11 | /** 12 | * Utility methods to ease {@link IntentDefinition} manipulation. 13 | */ 14 | public final class IntentUtils { 15 | 16 | /** 17 | * Disables the default constructor, this class only provides static methods and should not be constructed. 18 | */ 19 | private IntentUtils() { } 20 | 21 | /** 22 | * Returns {@code true} if the provided {@code parameter} refers to an {@link EntityType#ANY} entity. 23 | * 24 | * @param parameter the {@link ContextParameter} to check 25 | * @return {@code true} if the provided {@code parameter} refers to an {@link EntityType#ANY} entity 26 | * @throws NullPointerException if the provided {@code parameter} is {@code null} 27 | */ 28 | public static boolean isAnyParameter(@NonNull ContextParameter parameter) { 29 | if (parameter.getEntity().getReferredEntity() instanceof BaseEntityDefinition) { 30 | BaseEntityDefinition entity = (BaseEntityDefinition) parameter.getEntity().getReferredEntity(); 31 | return entity.getEntityType().equals(EntityType.ANY); 32 | } 33 | return false; 34 | } 35 | 36 | /** 37 | * Returns {@code true} if the provided {@code intent} contains a pure any training sentence. 38 | *

39 | * A pure any training sentence is a training sentence that entirely matches one of the 40 | * {@link ContextParameter#getTextFragments()} of an {@link EntityType#ANY} parameter of its containing intent. 41 | *

42 | * Example: 43 | *

44 |      * {@code
45 |      * intent(MyIntent)
46 |      *     .trainingSentence("VALUE")
47 |      *     .parameter("p").fromFragments("VALUE").entity(any());
48 |      * }
49 |      * 
50 | *

51 | * Pure any training sentences typically match any user input. 52 | *

53 | * Note: this method returns {@code true} if the provided {@code intent} contains a mix of pure any and 54 | * regular training sentences. 55 | * 56 | * @param intent the {@link IntentDefinition} to check 57 | * @return {@code true} if the provided {@code intent} contains a pure any training sentence 58 | * @throws NullPointerException if the provided {@code intent} is {@code null} 59 | * @see #isAnyParameter(ContextParameter) 60 | * @see #isPureAnyTrainingSentence(IntentDefinition, String) 61 | */ 62 | public static boolean hasPureAnyTrainingSentence(@NonNull IntentDefinition intent) { 63 | return intent.getTrainingSentences().stream().anyMatch(ts -> IntentUtils.isPureAnyTrainingSentence(intent, ts)); 64 | } 65 | 66 | /** 67 | * Returns {@code true} if the provided {@code trainingSentence} is a pure any training sentence of {@code intent}. 68 | *

69 | * A pure any training sentence is a training sentence that entirely matches one of the 70 | * {@link ContextParameter#getTextFragments()} of an {@link EntityType#ANY} parameter of its containing intent. 71 | *

72 | * Example: 73 | *

74 |      * {@code
75 |      * intent(MyIntent)
76 |      *     .trainingSentence("VALUE")
77 |      *     .parameter("p").fromFragments("VALUE").entity(any());
78 |      * }
79 |      * 
80 | *

81 | * Pure any training sentences typically match any user input. 82 | * 83 | * @param intent the {@link IntentDefinition} to containing the training sentence to check 84 | * @param trainingSentence the training sentence to check 85 | * @return {@code true} if the provided {@code trainingSentence} is a pure any training sentence of {@code intent} 86 | * @throws NullPointerException if the provided {@code intent} or {@code trainingSentence} is {@code null} 87 | * @throws IllegalArgumentException if the provided {@code intent} does not contain the {@code trainingSentence} 88 | * @see #isAnyParameter(ContextParameter) 89 | */ 90 | public static boolean isPureAnyTrainingSentence(@NonNull IntentDefinition intent, 91 | @NonNull String trainingSentence) { 92 | checkArgument(intent.getTrainingSentences().contains(trainingSentence), "Intent %s does not contain training " 93 | + "sentence\"%s\"", intent.getName(), trainingSentence); 94 | return intent.getParameters().stream() 95 | .anyMatch(p -> isAnyParameter(p) && trainingSentence.equals(p.getTextFragments().get(0))); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/xatkit/util/XatkitEnvironmentConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.util; 2 | 3 | import org.apache.commons.configuration2.MapConfiguration; 4 | 5 | import static java.util.Objects.isNull; 6 | import static java.util.Objects.nonNull; 7 | 8 | /** 9 | * A {@link MapConfiguration} initialized with {@link System#getenv()} variables. 10 | *

11 | * Unlike {@link org.apache.commons.configuration2.EnvironmentConfiguration}, {@link XatkitEnvironmentConfiguration} 12 | * allows to add new properties, and remove/clear loaded properties. This behavior is needed by Xatkit internal 13 | * classes, that dynamically add properties that can be reused by multiple components. 14 | *

15 | * Note that updating properties initialized from {@link System#getenv()} can lead to unexpected behavior. 16 | */ 17 | public class XatkitEnvironmentConfiguration extends MapConfiguration { 18 | 19 | /** 20 | * Creates a {@link XatkitEnvironmentConfiguration} initialized with {@link System#getenv()} values. 21 | */ 22 | public XatkitEnvironmentConfiguration() { 23 | super(System.getenv()); 24 | } 25 | 26 | /** 27 | * Retrieves the value associated to the provided {@code key}. 28 | *

29 | * This method first looks for an exact match of the provided {@code key}. If there is no value associated to it 30 | * (i.e. the method returns {@code null}) an additional lookup for environment variables is performed for {@code 31 | * key.toUpperCase().replaceAll("\\.", "_")}. See 32 | * the documentation 33 | * for additional information. 34 | * 35 | * @param key the key of the property to retrieve 36 | * @return the retrieved property value if it exists, {@code null} otherwise 37 | * @see #translateToEnvironmentVariable(String) 38 | */ 39 | @Override 40 | protected Object getPropertyInternal(String key) { 41 | Object value = super.getPropertyInternal(key); 42 | if (isNull(value)) { 43 | value = super.getPropertyInternal(this.translateToEnvironmentVariable(key)); 44 | } 45 | return value; 46 | } 47 | 48 | /** 49 | * Returns {@code true} if the configuration contains the provided {@code key}, {@code false} otherwise. 50 | *

51 | * This method first looks for an exact match of the provided {@code key}. If there is no value associated to it 52 | * (i.e. the method returns {@code false}) an additional lookup for environment variables is performed for {@code 53 | * key.toUpperCase().replaceAll("\\.", "_")}. See 54 | * the documentation 55 | * for additional information. 56 | * 57 | * @param key the key of the property to check 58 | * @return {@code true} if the configuration contains the provided {@code key}, {@code false} otherwise 59 | */ 60 | @Override 61 | protected boolean containsKeyInternal(String key) { 62 | boolean result = super.containsKeyInternal(key); 63 | if (!result) { 64 | result = super.containsKeyInternal(this.translateToEnvironmentVariable(key)); 65 | } 66 | return result; 67 | } 68 | 69 | /** 70 | * Translates the provided {@code key} to an environment variable name. 71 | *

72 | * This method returns the provided {@code key} in upper case, with its {@code .} replaced by {@code _} ({@code 73 | * key.toUpperCase().replaceAll("\\.", "_")}). See 74 | * the documentation 75 | * for additional information. 76 | * 77 | * @param key the key to translate to an environment variable name 78 | * @return the translated key 79 | */ 80 | private String translateToEnvironmentVariable(String key) { 81 | if (nonNull(key)) { 82 | return key.toUpperCase().replaceAll("\\.", "_"); 83 | } 84 | return null; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/interpreter/operation/object/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains Object-specific operation implementations for the Xatkit Common Language interpreter. 3 | */ 4 | package com.xatkit.core.interpreter.operation.object; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/interpreter/operation/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the abstract operations for the Xatkit Common Language interpreter. 3 | */ 4 | package com.xatkit.core.interpreter.operation; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/interpreter/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the Xatkit Common Language interpreter. 3 | */ 4 | package com.xatkit.core.interpreter; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the core components of the Xatkit framework. 3 | *

4 | * This package contains the {@link com.xatkit.core.XatkitBot} class, that is initialized with an execution 5 | * model. It also contains the different registries that are used to store model-level information and map them to 6 | * runtime-level classes. 7 | */ 8 | package com.xatkit.core; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/platform/action/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the abstract classes to implement to provide custom platform's actions. 3 | *

4 | * This package contains utility classes to implement regular actions, message-based actions, and provides a wrapper 5 | * for action result. These classes are implemented by Xatkit plugins, and dynamically instantiated by the core 6 | * components. 7 | * 8 | * @see com.xatkit.core 9 | * @see com.xatkit.plugins 10 | */ 11 | package com.xatkit.core.platform.action; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/platform/io/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the abstract classes to implement to provide custom platform's input provider. 3 | *

4 | * This package contains utility classes to implement intent providers (i.e. providers relying on a intent 5 | * recognition platform), as well as event providers (receiving and processing external events). These classes are 6 | * implemented by the Xatkit plugins, and dynamically instantiated by the core components. 7 | * 8 | * @see com.xatkit.core 9 | * @see com.xatkit.plugins 10 | */ 11 | package com.xatkit.core.platform.io; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/platform/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the abstract classes to implement to provide custom platforms. 3 | *

4 | * These classes are implemented by Xatkit plugins, and dynamically instantiated by the core components. 5 | * 6 | * @see com.xatkit.core 7 | * @see com.xatkit.plugins 8 | */ 9 | package com.xatkit.core.platform; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/recognition/dialogflow/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * An intent recognition provider implementation for the DialogFlow platform. 3 | */ 4 | package com.xatkit.core.recognition.dialogflow; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/recognition/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the abstract classes to implement to provide custom intent recognition. 3 | *

4 | * These abstract classes are implemented in the dialogflow package to support intent recognition from the 5 | * DialogFlow platform. Custom implementations are dynamically instantiated by 6 | * the core components. 7 | */ 8 | package com.xatkit.core.recognition; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/server/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the Xatkit server implementation. 3 | *

4 | * The Xatkit server is an experimental feature (i.e. not officially supported for now). It exposes a REST API that 5 | * can be used to send webhook events to the framework from remote services. These events are then handled by 6 | * specific event providers that transform them into Xatkit-compatible events. 7 | */ 8 | package com.xatkit.core.server; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/core/session/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the classes to manage sessions and contexts. 3 | *

4 | * These classes are implemented by custom intent recognition providers and event providers that are responsible of 5 | * synchronizing their remote context with the Xatkit one. 6 | * 7 | * @see com.xatkit.core.recognition 8 | */ 9 | package com.xatkit.core.session; -------------------------------------------------------------------------------- /src/main/javadoc/com/xatkit/util/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Utility classes that are used by the Xatkit framework. 3 | */ 4 | package com.xatkit.util; -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | %d{yyyy-MM-dd HH:mm:ss} %-5p %m%n 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/AbstractActionTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit; 2 | 3 | import com.xatkit.core.XatkitBot; 4 | import com.xatkit.core.platform.RuntimePlatform; 5 | import com.xatkit.core.platform.action.RuntimeAction; 6 | import com.xatkit.execution.ExecutionFactory; 7 | import com.xatkit.execution.StateContext; 8 | import org.junit.After; 9 | import org.junit.Before; 10 | 11 | import static java.util.Objects.nonNull; 12 | import static org.mockito.Mockito.mock; 13 | 14 | /** 15 | * A generic test case that defines utility methods to test {@link RuntimeAction} subclasses. 16 | *

17 | * Test cases targeting {@link RuntimeAction}s can extend this class to reuse the initialized {@link RuntimePlatform} 18 | * , an empty {@link StateContext}, as well as a mocked {@link XatkitBot} instance. This class takes care of the 19 | * life-cycle of the initialized {@link RuntimePlatform} and {@link XatkitBot}. 20 | * 21 | * @param the {@link RuntimeAction} {@link Class} under test 22 | * @param

the {@link RuntimePlatform} containing the action under test 23 | */ 24 | public abstract class AbstractActionTest, P extends RuntimePlatform> extends AbstractXatkitTest { 25 | 26 | /** 27 | * The {@link RuntimePlatform} instance containing the action under test. 28 | */ 29 | protected P platform; 30 | 31 | /** 32 | * The {@link RuntimeAction} instance under test. 33 | */ 34 | protected A action; 35 | 36 | /** 37 | * A mock of the {@link XatkitBot}. 38 | */ 39 | protected XatkitBot mockedXatkitBot; 40 | 41 | /** 42 | * An empty {@link StateContext} that can be used to create instances of the action under test. 43 | *

44 | * This context is reset before each test. 45 | */ 46 | protected StateContext context; 47 | 48 | /** 49 | * Initializes the {@link RuntimePlatform} and the empty {@link StateContext}. 50 | */ 51 | @Before 52 | public void setUp() { 53 | mockedXatkitBot = mock(XatkitBot.class); 54 | platform = getPlatform(); 55 | context = ExecutionFactory.eINSTANCE.createStateContext(); 56 | /* 57 | * This context was previously a XatkitSession instance. We keep the previous name in case some test cases 58 | * rely on it. 59 | */ 60 | context.setContextId("session"); 61 | } 62 | 63 | /** 64 | * Shutdown the {@link RuntimePlatform} containing the action under test. 65 | */ 66 | @After 67 | public void tearDown() { 68 | if (nonNull(platform)) { 69 | platform.shutdown(); 70 | } 71 | } 72 | 73 | /** 74 | * Returns an instance of the {@link RuntimePlatform} containing the action under test. 75 | *

76 | * This method must be implemented by subclasses and return a valid instance of {@link RuntimePlatform}. This 77 | * method is called before each test case to create a fresh {@link RuntimePlatform} instance. 78 | * 79 | * @return an instance of the {@link RuntimePlatform} containing the action under test 80 | */ 81 | protected abstract P getPlatform(); 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/AbstractEventProviderTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit; 2 | 3 | import com.xatkit.core.XatkitBot; 4 | import com.xatkit.core.platform.RuntimePlatform; 5 | import com.xatkit.core.platform.io.RuntimeEventProvider; 6 | import com.xatkit.core.recognition.IntentRecognitionProvider; 7 | import org.junit.After; 8 | import org.junit.Before; 9 | 10 | import static java.util.Objects.nonNull; 11 | import static org.mockito.Mockito.mock; 12 | import static org.mockito.Mockito.when; 13 | 14 | /** 15 | * A generic test case that defines utility methods to test {@link RuntimeEventProvider} subclasses. 16 | *

17 | * Test cases targeting {@link RuntimeEventProvider}s can extend this class to reuse the initialized 18 | * {@link RuntimePlatform} and a mocked {@link XatkitBot} instance. This class takes care of the life-cycle of the 19 | * initialized {@link RuntimePlatform} and {@link XatkitBot}. 20 | * 21 | * @param the {@link RuntimeEventProvider} {@link Class} under test 22 | * @param

the {@link RuntimePlatform} containing the provider under test 23 | */ 24 | public abstract class AbstractEventProviderTest, P extends RuntimePlatform> extends AbstractXatkitTest { 25 | 26 | /** 27 | * The {@link RuntimePlatform} instance containing the provider under test. 28 | */ 29 | protected P platform; 30 | 31 | /** 32 | * The {@link RuntimeEventProvider} instance under test. 33 | */ 34 | protected E provider; 35 | 36 | /** 37 | * A mock of the {@link XatkitBot}. 38 | */ 39 | protected XatkitBot mockedXatkitBot; 40 | 41 | /** 42 | * A mock of the {@link IntentRecognitionProvider}. 43 | *

44 | * This mock is returned when calling {@code mockedXatkitBot.getIntentRecognitionProvider()}. 45 | */ 46 | protected IntentRecognitionProvider mockedIntentRecognitionProvider; 47 | 48 | /** 49 | * Initializes the {@link RuntimePlatform}. 50 | */ 51 | @Before 52 | public void setUp() { 53 | mockedXatkitBot = mock(XatkitBot.class); 54 | mockedIntentRecognitionProvider = mock(IntentRecognitionProvider.class); 55 | when(mockedXatkitBot.getIntentRecognitionProvider()).thenReturn(mockedIntentRecognitionProvider); 56 | platform = getPlatform(); 57 | } 58 | 59 | /** 60 | * Shutdown the {@link RuntimePlatform} containing the action under test. 61 | */ 62 | @After 63 | public void tearDown() { 64 | if (nonNull(platform)) { 65 | platform.shutdown(); 66 | } 67 | } 68 | 69 | /** 70 | * Returns an instance of the {@link RuntimePlatform} containing the action under test. 71 | *

72 | * This method must be implemented by subclasses and return a valid instance of {@link RuntimePlatform}. This 73 | * method is called before each test case to create a fresh {@link RuntimePlatform} instance. 74 | * 75 | * @return an instance of the {@link RuntimePlatform} containing the action under test 76 | */ 77 | protected abstract P getPlatform(); 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/AbstractPlatformTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit; 2 | 3 | import com.xatkit.core.XatkitBot; 4 | import com.xatkit.core.platform.RuntimePlatform; 5 | import org.apache.commons.configuration2.BaseConfiguration; 6 | import org.apache.commons.configuration2.Configuration; 7 | import org.junit.After; 8 | import org.junit.Before; 9 | 10 | import static java.util.Objects.nonNull; 11 | import static org.mockito.Mockito.mock; 12 | 13 | /** 14 | * A generic test case that defines utility methods to test {@link RuntimePlatform} subclasses. 15 | *

16 | * Test cases targeting {@link RuntimePlatform}s can extend this class to reuse a mocked {@link XatkitBot}, and an 17 | * initialized {@link Configuration}. 18 | * 19 | * @param

the {@link RuntimePlatform} {@link Class} under test 20 | */ 21 | public class AbstractPlatformTest

extends AbstractXatkitTest { 22 | 23 | /** 24 | * The {@link RuntimePlatform} under test 25 | */ 26 | protected P platform; 27 | 28 | /** 29 | * A mock of the {@link XatkitBot}. 30 | */ 31 | protected XatkitBot mockedXatkitBot; 32 | 33 | /** 34 | * A default configuration that can be reused by subclasses. 35 | */ 36 | protected Configuration configuration; 37 | 38 | /** 39 | * Initializes the mocked {@link XatkitBot} and the default {@link Configuration}. 40 | */ 41 | @Before 42 | public void setUp() { 43 | mockedXatkitBot = mock(XatkitBot.class); 44 | configuration = new BaseConfiguration(); 45 | } 46 | 47 | /** 48 | * Shutdowns the {@link RuntimePlatform}. 49 | */ 50 | @After 51 | public void tearDown() { 52 | if(nonNull(platform)) { 53 | platform.shutdown(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/AbstractXatkitTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit; 2 | 3 | import fr.inria.atlanmod.commons.log.Log; 4 | import org.junit.Rule; 5 | import org.junit.rules.TestRule; 6 | import org.junit.rules.TestWatcher; 7 | import org.junit.runner.Description; 8 | 9 | import java.time.Duration; 10 | import java.time.Instant; 11 | 12 | /** 13 | * A generic test case that defines utility methods and JUnit {@link Rule}s to use in Xatkit test cases. 14 | *

15 | * All the Xatkit tests should extend this utility class, that adds execution logs before/after executing each test 16 | * method, easing build issue debugging. 17 | */ 18 | public abstract class AbstractXatkitTest { 19 | 20 | /** 21 | * The {@link TestWatcher} used to log execution information when starting and finishing a test method execution. 22 | */ 23 | @Rule 24 | public TestRule watcher = new TestWatcher() { 25 | 26 | /** 27 | * The test method execution starting {@link Instant}. 28 | */ 29 | private Instant startingInstant; 30 | 31 | /** 32 | * Adds an utility log displaying the name of the current executed method. 33 | * @param description the {@link Description} of the executed test method 34 | */ 35 | @Override 36 | protected void starting(Description description) { 37 | startingInstant = Instant.now(); 38 | Log.info("Starting test {0}.{1}", description.getClassName(), description.getMethodName()); 39 | } 40 | 41 | /** 42 | * Adds an utility log displaying the name of the executed method and its computation time. 43 | * @param description the {@link Description} of the executed test method 44 | */ 45 | @Override 46 | protected void finished(Description description) { 47 | Instant finishedInstant = Instant.now(); 48 | Log.info("Test {0}.{1} completed in {2} ms", description.getClassName(), description.getMethodName(), 49 | Duration.between(startingInstant, finishedInstant).toMillis()); 50 | } 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/platform/RuntimePlatformTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.platform; 2 | 3 | import com.xatkit.AbstractPlatformTest; 4 | import com.xatkit.core.platform.io.RuntimeEventProvider; 5 | import com.xatkit.core.platform.io.WebhookEventProvider; 6 | import com.xatkit.core.server.XatkitServer; 7 | import com.xatkit.stubs.EmptyRuntimePlatform; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | import static org.mockito.Mockito.doAnswer; 13 | import static org.mockito.Mockito.mock; 14 | import static org.mockito.Mockito.verify; 15 | import static org.mockito.Mockito.when; 16 | 17 | public class RuntimePlatformTest extends AbstractPlatformTest { 18 | 19 | private RuntimeEventProvider mockedEventProvider; 20 | 21 | private WebhookEventProvider mockedWebhookProvider; 22 | 23 | private XatkitServer mockedXatkitServer; 24 | 25 | @Before 26 | public void setUp() { 27 | super.setUp(); 28 | this.mockedEventProvider = mock(RuntimeEventProvider.class); 29 | this.mockedWebhookProvider = mock(WebhookEventProvider.class); 30 | this.mockedXatkitServer = mock(XatkitServer.class); 31 | when(mockedXatkitBot.getXatkitServer()).thenReturn(mockedXatkitServer); 32 | doAnswer(invocationOnMock -> { 33 | /* 34 | * We need to wait here to be sure the provider's Thread is running (otherwise the computation finishes 35 | * before we can check it) 36 | */ 37 | synchronized (this) { 38 | try { 39 | wait(); 40 | } catch(InterruptedException e) { 41 | 42 | } 43 | } 44 | return null; 45 | }).when(mockedEventProvider).run(); 46 | doAnswer(invocationOnMock -> { 47 | synchronized (this) { 48 | try { 49 | wait(); 50 | } catch(InterruptedException e) { 51 | 52 | } 53 | } 54 | return null; 55 | }).when(mockedWebhookProvider).run(); 56 | this.platform = getPlatform(); 57 | } 58 | 59 | @Test 60 | public void getName() { 61 | assertThat(platform.getName()).as("Valid runtimePlatform name").isEqualTo("EmptyRuntimePlatform"); 62 | } 63 | 64 | @Test 65 | public void getConfigurationNotStarted() { 66 | assertThat(platform.getConfiguration()).isNull(); 67 | } 68 | 69 | @Test 70 | public void getConfigurationStarted() { 71 | platform.start(mockedXatkitBot, configuration); 72 | assertThat(platform.getConfiguration()).as("Not null Configuration").isNotNull(); 73 | } 74 | 75 | @Test 76 | public void getXatkitBotNotStarted() { 77 | assertThat(platform.getXatkitBot()).isNull(); 78 | } 79 | 80 | @Test 81 | public void getXatkitBotStarted() { 82 | platform.start(mockedXatkitBot, configuration); 83 | assertThat(platform.getXatkitBot()).as("Not null XatkitBot").isNotNull(); 84 | assertThat(platform.getXatkitBot()).as("Valid XatkitBot").isEqualTo(mockedXatkitBot); 85 | } 86 | 87 | @Test(expected = NullPointerException.class) 88 | public void startEventProviderNullEventProviderDefinition() { 89 | platform.start(mockedXatkitBot, configuration); 90 | platform.startEventProvider(null); 91 | } 92 | 93 | @Test 94 | public void startEventProvider() { 95 | platform.start(mockedXatkitBot, configuration); 96 | platform.startEventProvider(mockedEventProvider); 97 | assertThat(platform.eventProviderMap).containsKey(mockedEventProvider.getClass().getSimpleName()); 98 | RuntimePlatform.EventProviderThread eventProviderThread = 99 | platform.eventProviderMap.get(mockedEventProvider.getClass().getSimpleName()); 100 | assertThat(eventProviderThread.getRuntimeEventProvider()).isInstanceOf(RuntimeEventProvider.class); 101 | assertThat(eventProviderThread.isAlive()).isTrue(); 102 | } 103 | 104 | @Test 105 | public void startValidEventProviderWebhook() { 106 | platform.start(mockedXatkitBot, configuration); 107 | platform.startEventProvider(mockedWebhookProvider); 108 | assertThat(platform.eventProviderMap).containsKey(mockedWebhookProvider.getClass().getSimpleName()); 109 | RuntimePlatform.EventProviderThread eventProviderThread = 110 | platform.eventProviderMap.get(mockedWebhookProvider.getClass().getSimpleName()); 111 | assertThat(eventProviderThread.getRuntimeEventProvider()).isInstanceOf(WebhookEventProvider.class); 112 | assertThat(eventProviderThread.isAlive()).isTrue(); 113 | verify(mockedXatkitServer).registerWebhookEventProvider(mockedWebhookProvider); 114 | } 115 | 116 | @Test 117 | public void shutdownRegisteredEventProviderAndActionDefinition() { 118 | platform.start(mockedXatkitBot, configuration); 119 | platform.startEventProvider(mockedEventProvider); 120 | // Enables the actionDefinition in the RuntimePlatform 121 | platform.shutdown(); 122 | assertThat(platform.getEventProviderMap()).as("Empty RuntimeEventProvider map").isEmpty(); 123 | } 124 | 125 | public RuntimePlatform getPlatform() { 126 | return new EmptyRuntimePlatform(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/platform/action/RuntimeActionResultTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.platform.action; 2 | 3 | import com.xatkit.AbstractXatkitTest; 4 | import org.junit.Test; 5 | 6 | import static org.assertj.core.api.Assertions.assertThat; 7 | 8 | public class RuntimeActionResultTest extends AbstractXatkitTest { 9 | 10 | private RuntimeActionResult result; 11 | 12 | @Test 13 | public void constructNullResultValidExecutionTime() { 14 | result = new RuntimeActionResult(null, 3); 15 | assertThat(result.getResult()).as("Null result").isNull(); 16 | assertThat(result.getExecutionTime()).as("Valid execution time").isEqualTo(3); 17 | assertActionResultIsNotErrorOrException(result); 18 | } 19 | 20 | @Test 21 | public void constructNotNullResultValidExecutionTime() { 22 | Integer rawResult = new Integer(10); 23 | result = new RuntimeActionResult(rawResult, 3); 24 | assertThat(result.getResult()).as("Valid result").isEqualTo(rawResult); 25 | assertThat(result.getExecutionTime()).as("Valid execution time").isEqualTo(3); 26 | assertActionResultIsNotErrorOrException(result); 27 | } 28 | 29 | @Test(expected = IllegalArgumentException.class) 30 | public void constructNullResultInvalidExecutionTime() { 31 | result = new RuntimeActionResult(null, -1); 32 | } 33 | 34 | @Test(expected = IllegalArgumentException.class) 35 | public void constructNotNullResultInvalidExecutionTime() { 36 | result = new RuntimeActionResult(new Integer(10), -1); 37 | } 38 | 39 | @Test 40 | public void constructNullResultNotNullExceptionValidExecutionTime() { 41 | Exception e = new RuntimeException("message"); 42 | result = new RuntimeActionResult(null, e, 3); 43 | assertThat(result.getResult()).as("Null result").isNull(); 44 | assertThat(result.getExecutionTime()).as("Valid execution time").isEqualTo(3); 45 | assertThat(result.getThrowable()).as("Valid exception").isEqualTo(e); 46 | assertThat(result.isError()).as("Is error").isTrue(); 47 | } 48 | 49 | @Test 50 | public void constructNullResultNullExceptionValidExecutionTime() { 51 | result = new RuntimeActionResult(null, null, 3); 52 | assertThat(result.getResult()).as("Null result").isNull(); 53 | assertThat(result.getExecutionTime()).as("Valid execution time").isEqualTo(3); 54 | assertThat(result.getThrowable()).as("Null exception").isNull(); 55 | assertThat(result.isError()).as("Not error").isFalse(); 56 | } 57 | 58 | @Test 59 | public void constructNotNullResultNotNullExceptionValidExecutionTime() { 60 | Integer rawResult = new Integer(10); 61 | Exception e = new RuntimeException("message"); 62 | result = new RuntimeActionResult(rawResult, e, 3); 63 | assertThat(result.getResult()).as("Valid result").isEqualTo(rawResult); 64 | assertThat(result.getExecutionTime()).as("Valid execution time").isEqualTo(3); 65 | assertThat(result.getThrowable()).as("Valid exception").isEqualTo(e); 66 | assertThat(result.isError()).as("Is error").isTrue(); 67 | } 68 | 69 | @Test 70 | public void constructNotNullResultNullExceptionValidExecutionTime() { 71 | Integer rawResult = new Integer(10); 72 | result = new RuntimeActionResult(rawResult, null, 3); 73 | assertThat(result.getResult()).as("Valid result").isEqualTo(rawResult); 74 | assertThat(result.getExecutionTime()).as("Valid execution time").isEqualTo(3); 75 | assertThat(result.getThrowable()).as("Null exception").isNull(); 76 | assertThat(result.isError()).as("Not error").isFalse(); 77 | } 78 | 79 | @Test(expected = IllegalArgumentException.class) 80 | public void constructNullResultNotNullExceptionInvalidExecutionTime() { 81 | result = new RuntimeActionResult(null, new RuntimeException("message"), -1); 82 | } 83 | 84 | @Test(expected = IllegalArgumentException.class) 85 | public void constructNullResultNullExceptionInvalidExecutionTime() { 86 | result = new RuntimeActionResult(null, null, -1); 87 | } 88 | 89 | @Test(expected = IllegalArgumentException.class) 90 | public void constructNotNullResultNotNullExceptionInvalidExecutionTime() { 91 | result = new RuntimeActionResult(new Integer(10), new RuntimeException("message"), -1); 92 | } 93 | 94 | @Test(expected = IllegalArgumentException.class) 95 | public void constructNotNullResultNullExceptionInvalidExecutionTime() { 96 | result = new RuntimeActionResult(new Integer(10), null, -1); 97 | } 98 | 99 | /* 100 | * No need to test the getters, they are already tested in the constructor tests. 101 | */ 102 | 103 | /* 104 | * Checks the {@code result} values that should not be modified after calling RuntimeActionResult(Object, long). 105 | */ 106 | private void assertActionResultIsNotErrorOrException(RuntimeActionResult result) { 107 | assertThat(result.getThrowable()).as("No thrown exception").isNull(); 108 | assertThat(result.isError()).as("Not error").isFalse(); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/recognition/AbstractIntentRecognitionProviderTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition; 2 | 3 | import com.xatkit.AbstractXatkitTest; 4 | import com.xatkit.execution.ExecutionFactory; 5 | import com.xatkit.execution.State; 6 | import com.xatkit.execution.StateContext; 7 | import com.xatkit.intent.IntentFactory; 8 | import com.xatkit.intent.RecognizedIntent; 9 | import com.xatkit.library.core.CoreLibrary; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | 13 | import java.util.Arrays; 14 | import java.util.Collection; 15 | import java.util.Collections; 16 | 17 | import static org.assertj.core.api.Assertions.assertThat; 18 | import static org.mockito.ArgumentMatchers.any; 19 | import static org.mockito.ArgumentMatchers.anyCollection; 20 | import static org.mockito.Mockito.doCallRealMethod; 21 | import static org.mockito.Mockito.mock; 22 | import static org.mockito.Mockito.when; 23 | 24 | public class AbstractIntentRecognitionProviderTest extends AbstractXatkitTest { 25 | 26 | private AbstractIntentRecognitionProvider provider; 27 | 28 | private RecognizedIntent help; 29 | 30 | private RecognizedIntent greetings; 31 | 32 | private StateContext stateContext; 33 | 34 | private State initState; 35 | 36 | @Before 37 | public void setUp() { 38 | provider = mock(AbstractIntentRecognitionProvider.class); 39 | doCallRealMethod().when(provider).getBestCandidate(anyCollection(), any()); 40 | help = IntentFactory.eINSTANCE.createRecognizedIntent(); 41 | help.setDefinition(CoreLibrary.Help); 42 | help.setRecognitionConfidence(1); 43 | greetings = IntentFactory.eINSTANCE.createRecognizedIntent(); 44 | greetings.setDefinition(CoreLibrary.Greetings); 45 | greetings.setRecognitionConfidence(.5f); 46 | stateContext = ExecutionFactory.eINSTANCE.createStateContext(); 47 | stateContext.setContextId("ContextID"); 48 | initState = mock(State.class); 49 | stateContext.setState(initState); 50 | } 51 | 52 | @Test 53 | public void getBestCandidateSingleSolution() { 54 | Collection candidates = Arrays.asList(help, greetings); 55 | when(initState.getAllAccessedIntents()).thenReturn(Collections.singletonList(CoreLibrary.Help)); 56 | RecognizedIntent bestCandidate = provider.getBestCandidate(candidates, stateContext); 57 | assertThat(bestCandidate).isEqualTo(help); 58 | } 59 | 60 | @Test 61 | public void getBestCandidateMultipleSolutions() { 62 | Collection candidates = Arrays.asList(help, greetings); 63 | when(initState.getAllAccessedIntents()).thenReturn(Arrays.asList(CoreLibrary.Help, CoreLibrary.Greetings)); 64 | RecognizedIntent bestCandidate = provider.getBestCandidate(candidates, stateContext); 65 | /* 66 | * Make sure we have the best option here, even if the other one is possible. 67 | */ 68 | assertThat(bestCandidate).isEqualTo(help); 69 | } 70 | 71 | @Test 72 | public void getBestCandidateMultipleSolutionResultNotFirstInCollection() { 73 | Collection candidates = Arrays.asList(greetings, help); 74 | when(initState.getAllAccessedIntents()).thenReturn(Arrays.asList(CoreLibrary.Help, CoreLibrary.Greetings)); 75 | RecognizedIntent bestCandidate = provider.getBestCandidate(candidates, stateContext); 76 | /* 77 | * Make sure we have the best option here, even if it's not the first match in the collection. 78 | */ 79 | assertThat(bestCandidate).isEqualTo(help); 80 | } 81 | 82 | @Test 83 | public void getBestCandidateNoSolution() { 84 | Collection candidates = Arrays.asList(help, greetings); 85 | when(initState.getAllAccessedIntents()).thenReturn(Collections.emptyList()); 86 | RecognizedIntent bestCandidate = provider.getBestCandidate(candidates, stateContext); 87 | assertThat(bestCandidate.getDefinition()).isEqualTo(IntentRecognitionProvider.DEFAULT_FALLBACK_INTENT); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/recognition/processor/PostProcessorNoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition.processor; 2 | 3 | import com.xatkit.core.recognition.IntentRecognitionProviderFactoryTest; 4 | import com.xatkit.execution.StateContext; 5 | import com.xatkit.intent.RecognizedIntent; 6 | import lombok.Getter; 7 | import org.apache.commons.configuration2.Configuration; 8 | 9 | /** 10 | * Stub class for 11 | * {@link IntentRecognitionProviderFactoryTest#getIntentRecognitionProviderWithPostProcessor()}. 12 | */ 13 | public class PostProcessorNoConfiguration implements IntentPostProcessor { 14 | 15 | @Override 16 | public RecognizedIntent process(RecognizedIntent recognizedIntent, StateContext context) { 17 | return null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/recognition/processor/PostProcessorWithConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition.processor; 2 | 3 | import com.xatkit.execution.StateContext; 4 | import com.xatkit.intent.RecognizedIntent; 5 | import lombok.Getter; 6 | import org.apache.commons.configuration2.Configuration; 7 | 8 | /** 9 | * Stub class for 10 | * {@link com.xatkit.core.recognition.IntentRecognitionProviderFactoryTest#getIntentRecognitionProviderWithPostProcessorConstructedWithConfiguration()}. 11 | */ 12 | public class PostProcessorWithConfiguration implements IntentPostProcessor { 13 | 14 | @Getter 15 | private Configuration configuration; 16 | 17 | public PostProcessorWithConfiguration(Configuration configuration) { 18 | this.configuration = configuration; 19 | } 20 | 21 | @Override 22 | public RecognizedIntent process(RecognizedIntent recognizedIntent, StateContext context) { 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/recognition/processor/PreProcessorNoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition.processor; 2 | 3 | import com.xatkit.core.recognition.IntentRecognitionProviderFactoryTest; 4 | import com.xatkit.execution.StateContext; 5 | import com.xatkit.intent.RecognizedIntent; 6 | 7 | /** 8 | * Stub class for 9 | * {@link IntentRecognitionProviderFactoryTest#getIntentRecognitionProviderWithPreProcessor()}. 10 | */ 11 | public class PreProcessorNoConfiguration implements InputPreProcessor { 12 | 13 | @Override 14 | public String process(String input, StateContext context) { 15 | return null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/recognition/regex/RegExIntentRecognitionProviderTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.recognition.regex; 2 | 3 | import com.xatkit.core.recognition.IntentRecognitionProviderException; 4 | import com.xatkit.core.recognition.IntentRecognitionProviderTest; 5 | import com.xatkit.execution.ExecutionFactory; 6 | import com.xatkit.execution.StateContext; 7 | import com.xatkit.intent.IntentDefinition; 8 | import com.xatkit.intent.IntentFactory; 9 | import com.xatkit.intent.RecognizedIntent; 10 | import com.xatkit.stubs.TestingStateContext; 11 | import org.apache.commons.configuration2.BaseConfiguration; 12 | import org.junit.Ignore; 13 | import org.junit.Test; 14 | 15 | import static org.assertj.core.api.Java6Assertions.assertThat; 16 | 17 | public class RegExIntentRecognitionProviderTest extends IntentRecognitionProviderTest { 18 | 19 | @Test(expected = NullPointerException.class) 20 | public void constructNullConfiguration() { 21 | intentRecognitionProvider = new RegExIntentRecognitionProvider(null, null); 22 | } 23 | 24 | @Test 25 | public void constructValidConfiguration() { 26 | intentRecognitionProvider = new RegExIntentRecognitionProvider(new BaseConfiguration(), null); 27 | assertThat(intentRecognitionProvider.isShutdown()).as("Provider not shut down").isFalse(); 28 | } 29 | 30 | @Ignore 31 | /* 32 | * Should be enabled to test #261 (https://github.com/xatkit-bot-platform/xatkit-runtime/issues/261) 33 | */ 34 | @Test 35 | public void getIntentValidIntentDefinitionWithOutContextMappingUpperCase() throws IntentRecognitionProviderException { 36 | intentRecognitionProvider = getIntentRecognitionProvider(); 37 | intentRecognitionProvider.registerEntityDefinition(intentProviderTestBot.getMappingEntity()); 38 | intentRecognitionProvider.registerIntentDefinition(intentProviderTestBot.getMappingEntityIntent()); 39 | StateContext context = ExecutionFactory.eINSTANCE.createStateContext(); 40 | context.setContextId("contextId"); 41 | RecognizedIntent recognizedIntent = intentRecognitionProvider.getIntent(("Give me some information about " + 42 | "Gwendal").toUpperCase(), context); 43 | assertThatRecognizedIntentHasDefinition(recognizedIntent, 44 | intentProviderTestBot.getMappingEntityIntent().getName()); 45 | assertThatIntentContainsParameter(recognizedIntent, "name"); 46 | assertThatIntentContainsParameterWithValue(recognizedIntent, "name", "Gwendal"); 47 | } 48 | 49 | @Test 50 | public void getIntentValidIntentDefinitionNoOutContextUpperCase() throws IntentRecognitionProviderException { 51 | intentRecognitionProvider = getIntentRecognitionProvider(); 52 | intentRecognitionProvider.registerIntentDefinition(intentProviderTestBot.getSimpleIntent()); 53 | TestingStateContext context = contextFactory.wrap(intentRecognitionProvider.createContext("contextId")); 54 | context.enableIntents(intentProviderTestBot.getSimpleIntent()); 55 | RecognizedIntent recognizedIntent = intentRecognitionProvider.getIntent("Greetings".toUpperCase(), 56 | context); 57 | assertThatRecognizedIntentHasDefinition(recognizedIntent, intentProviderTestBot.getSimpleIntent().getName()); 58 | } 59 | 60 | @Test 61 | public void getIntentValidIntentDefinitionWithReservedRegExpCharacters() throws IntentRecognitionProviderException { 62 | intentRecognitionProvider = getIntentRecognitionProvider(); 63 | IntentDefinition intentDefinition = IntentFactory.eINSTANCE.createIntentDefinition(); 64 | intentDefinition.setName("TestReservedRegExpCharacters"); 65 | intentDefinition.getTrainingSentences().add("$test"); 66 | intentRecognitionProvider.registerIntentDefinition(intentDefinition); 67 | TestingStateContext context = contextFactory.wrap(intentRecognitionProvider.createContext("contextId")); 68 | context.enableIntents(intentDefinition); 69 | RecognizedIntent recognizedIntent = intentRecognitionProvider.getIntent("$test", context); 70 | assertThatRecognizedIntentHasDefinition(recognizedIntent, intentDefinition.getName()); 71 | } 72 | 73 | @Ignore 74 | @Test 75 | @Override 76 | public void getCompositeEntityIntent() throws IntentRecognitionProviderException { 77 | /* 78 | * Composite entities are not supported in the RegExp provider (see https://github 79 | * .com/xatkit-bot-platform/xatkit-runtime/issues/272) 80 | */ 81 | super.getCompositeEntityIntent(); 82 | } 83 | 84 | @Override 85 | protected RegExIntentRecognitionProvider getIntentRecognitionProvider() { 86 | return new RegExIntentRecognitionProvider(new BaseConfiguration(), null); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/server/HttpUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.server; 2 | 3 | import com.xatkit.AbstractXatkitTest; 4 | import org.apache.http.HttpRequest; 5 | import org.apache.http.NameValuePair; 6 | import org.apache.http.client.utils.URIBuilder; 7 | import org.apache.http.message.BasicHttpRequest; 8 | import org.apache.http.message.BasicNameValuePair; 9 | import org.junit.BeforeClass; 10 | import org.junit.Test; 11 | 12 | import java.net.URISyntaxException; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | 16 | import static org.assertj.core.api.Assertions.assertThat; 17 | 18 | public class HttpUtilsTest extends AbstractXatkitTest { 19 | 20 | private static String VALID_HTTP_REQUEST_PATH = "/target"; 21 | 22 | private static HttpRequest VALID_HTTP_REQUEST; 23 | 24 | private static HttpRequest INVALID_HTTP_REQUEST; 25 | 26 | private static List TEST_PARAMETERS = Arrays.asList(new BasicNameValuePair("param1", "abc"), 27 | new BasicNameValuePair("param2", "def")); 28 | 29 | @BeforeClass 30 | public static void setUpBeforeClass() { 31 | VALID_HTTP_REQUEST = new BasicHttpRequest("GET", VALID_HTTP_REQUEST_PATH); 32 | INVALID_HTTP_REQUEST = new BasicHttpRequest("GET", "i\nvalid"); 33 | } 34 | 35 | @Test(expected = NullPointerException.class) 36 | public void getURIBuilderFromNullRequest() throws URISyntaxException { 37 | HttpUtils.getURIBuilderFrom(null); 38 | } 39 | 40 | @Test(expected = URISyntaxException.class) 41 | public void getURIBuilderFromInvalidURI() throws URISyntaxException { 42 | HttpUtils.getURIBuilderFrom(INVALID_HTTP_REQUEST); 43 | } 44 | 45 | @Test 46 | public void getURIBuilderFromValidURI() throws URISyntaxException { 47 | URIBuilder uriBuilder = HttpUtils.getURIBuilderFrom(VALID_HTTP_REQUEST); 48 | assertThat(uriBuilder.getPath()).as("Builder contains the correct path").isEqualTo(VALID_HTTP_REQUEST_PATH); 49 | } 50 | 51 | @Test(expected = NullPointerException.class) 52 | public void getPathNullRequest() throws URISyntaxException { 53 | HttpUtils.getPath(null); 54 | } 55 | 56 | @Test(expected = URISyntaxException.class) 57 | public void getPathInvalidURI() throws URISyntaxException { 58 | HttpUtils.getPath(INVALID_HTTP_REQUEST); 59 | } 60 | 61 | @Test 62 | public void getPathValidURI() throws URISyntaxException { 63 | String path = HttpUtils.getPath(VALID_HTTP_REQUEST); 64 | assertThat(path).as("Correct path").isEqualTo(VALID_HTTP_REQUEST_PATH); 65 | } 66 | 67 | @Test(expected = NullPointerException.class) 68 | public void getParametersNullRequest() throws URISyntaxException { 69 | HttpUtils.getParameters(null); 70 | } 71 | 72 | @Test(expected = URISyntaxException.class) 73 | public void getParametersInvalidURI() throws URISyntaxException { 74 | HttpUtils.getParameters(INVALID_HTTP_REQUEST); 75 | } 76 | 77 | @Test 78 | public void getParametersValidURINoParameters() throws URISyntaxException { 79 | List parameters = HttpUtils.getParameters(VALID_HTTP_REQUEST); 80 | assertThat(parameters).as("Parameter list is empty").isEmpty(); 81 | } 82 | 83 | @Test 84 | public void getParametersValidURIWithParameters() throws URISyntaxException { 85 | List parameters = HttpUtils.getParameters(new BasicHttpRequest("GET", 86 | VALID_HTTP_REQUEST_PATH + "?param1=abc¶m2=def")); 87 | assertThat(parameters).as("Parameters list contains two parameters").hasSize(2); 88 | assertThat(parameters.stream()).as("Parameter list contains param1").anyMatch(p -> p.getName().equals("param1" 89 | ) && p.getValue().equals("abc")); 90 | assertThat(parameters.stream()).as("Parameter list contains param2").anyMatch(p -> p.getName().equals("param2" 91 | ) && p.getValue().equals("def")); 92 | } 93 | 94 | @Test(expected = NullPointerException.class) 95 | public void getParameterValueNullName() { 96 | HttpUtils.getParameterValue(null, TEST_PARAMETERS); 97 | } 98 | 99 | @Test(expected = NullPointerException.class) 100 | public void getParameterValueNullParameters() { 101 | HttpUtils.getParameterValue("param1", null); 102 | } 103 | 104 | @Test 105 | public void getParameterValueExistingParameter() { 106 | String value = HttpUtils.getParameterValue("param1", TEST_PARAMETERS); 107 | assertThat(value).as("Valid parameter value").isEqualTo("abc"); 108 | } 109 | 110 | @Test 111 | public void getParameterValueNotExistingParameter() { 112 | String value = HttpUtils.getParameterValue("invalid", TEST_PARAMETERS); 113 | assertThat(value).as("Parameter value is null").isNull(); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/session/StateContextTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.session; 2 | 3 | import com.xatkit.AbstractXatkitTest; 4 | import com.xatkit.execution.ExecutionFactory; 5 | import com.xatkit.execution.State; 6 | import com.xatkit.execution.StateContext; 7 | import lombok.val; 8 | import org.assertj.core.api.JUnitSoftAssertions; 9 | import org.junit.Rule; 10 | import org.junit.Test; 11 | 12 | import static com.xatkit.dsl.DSL.intent; 13 | import static com.xatkit.dsl.DSL.intentIs; 14 | import static com.xatkit.dsl.DSL.state; 15 | import static org.assertj.core.api.Assertions.assertThat; 16 | 17 | public class StateContextTest extends AbstractXatkitTest { 18 | 19 | private static State TEST_STATE = ExecutionFactory.eINSTANCE.createState(); 20 | 21 | static { 22 | TEST_STATE.setName("Test_State"); 23 | } 24 | 25 | private StateContext context; 26 | 27 | @Rule 28 | public final JUnitSoftAssertions softly = new JUnitSoftAssertions(); 29 | 30 | @Test 31 | public void getStateNewSession() { 32 | context = ExecutionFactory.eINSTANCE.createStateContext(); 33 | context.setContextId("contextId"); 34 | assertThat(context.getState()).as("Session state is null").isNull(); 35 | } 36 | 37 | @Test 38 | public void setStateNewSession() { 39 | context = ExecutionFactory.eINSTANCE.createStateContext(); 40 | context.setContextId("contextId"); 41 | context.setState(TEST_STATE); 42 | assertThat(context.getState()).as("State has been set").isEqualTo(TEST_STATE); 43 | } 44 | 45 | @Test 46 | public void setStateErasePreviousState() { 47 | context = ExecutionFactory.eINSTANCE.createStateContext(); 48 | context.setContextId("contextId"); 49 | context.setState(TEST_STATE); 50 | State testState2 = ExecutionFactory.eINSTANCE.createState(); 51 | testState2.setName("Test_State2"); 52 | context.setState(testState2); 53 | assertThat(context.getState()).as("State correctly erased").isEqualTo(testState2); 54 | } 55 | 56 | @Test 57 | public void setStateWithComposedTransitionCondition() { 58 | context = ExecutionFactory.eINSTANCE.createStateContext(); 59 | context.setContextId("contextId"); 60 | val intent = intent("Intent") 61 | .trainingSentence("Hi"); 62 | val state = state("State") 63 | .next() 64 | /* 65 | * The actual and condition doesn't matter here. 66 | */ 67 | .when(intentIs(intent).and(context -> context.getSession().containsKey("test"))).moveTo(TEST_STATE) 68 | .getState(); 69 | context.setState(state); 70 | assertThat(context.getState()).isEqualTo(state); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/util/LoaderTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.util; 2 | 3 | import com.xatkit.AbstractXatkitTest; 4 | import com.xatkit.core.util.stubs.ExceptionClass; 5 | import com.xatkit.core.util.stubs.LoadableClass; 6 | import com.xatkit.util.Loader; 7 | import org.junit.Test; 8 | 9 | import java.lang.reflect.InvocationTargetException; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | public class LoaderTest extends AbstractXatkitTest { 14 | 15 | @Test 16 | public void constructValidParameters() throws Exception { 17 | LoadableClass loaded = Loader.construct(LoadableClass.class, new String[]{"test", "test2"}); 18 | assertThat(loaded).as("Not null").isNotNull(); 19 | } 20 | 21 | @Test(expected = InvocationTargetException.class) 22 | public void constructExceptionInConstructor() throws Exception { 23 | ExceptionClass loaded = Loader.construct(ExceptionClass.class, new String[]{"test", "test2"}); 24 | } 25 | 26 | @Test(expected = NoSuchMethodException.class) 27 | public void constructInvalidParameters() throws Exception { 28 | LoadableClass loaded = Loader.construct(LoadableClass.class, new Object[]{"test", 1}); 29 | } 30 | 31 | @Test(expected = NoSuchMethodException.class) 32 | public void constructTooManyParameters() throws Exception { 33 | LoadableClass loaded = Loader.construct(LoadableClass.class, new Object[]{"test", "test", "test"}); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/util/stubs/ExceptionClass.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.util.stubs; 2 | 3 | /** 4 | * A {@link Class} that always throws an exception when constructed. 5 | *

6 | * This class is used to test the Xatkit {@link com.xatkit.util.Loader}. 7 | */ 8 | public class ExceptionClass { 9 | 10 | public ExceptionClass(String s1, String s2) { 11 | throw new RuntimeException("Error"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/core/util/stubs/LoadableClass.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.core.util.stubs; 2 | 3 | /** 4 | * A {@link Class} that can be constructed with two {@link String} parameters. 5 | *

6 | * This class is used to test the Xatkit {@link com.xatkit.util.Loader}. 7 | */ 8 | public class LoadableClass { 9 | 10 | private String s1; 11 | private String s2; 12 | 13 | public LoadableClass(String s1, String s2) { 14 | this.s1 = s1; 15 | this.s2 = s2; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/dsl/EventTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl; 2 | 3 | import com.xatkit.intent.EventDefinition; 4 | import lombok.val; 5 | import org.junit.Test; 6 | 7 | import static com.xatkit.dsl.DSL.event; 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | public class EventTest { 11 | 12 | @Test 13 | public void eventWithoutContext() { 14 | val event = event("Event"); 15 | EventDefinition base = event.getEventDefinition(); 16 | assertThat(base.getName()).isEqualTo("Event"); 17 | assertThat(base.getParameters()).isEmpty(); 18 | } 19 | 20 | @Test 21 | public void eventWithContext() { 22 | val event = event("Event") 23 | .parameter("p1") 24 | .parameter("p2") 25 | .parameter("p3") 26 | .parameter("p4"); 27 | 28 | EventDefinition base = event.getEventDefinition(); 29 | assertThat(base.getName()).isEqualTo("Event"); 30 | assertThat(base.getParameters()).hasSize(4); 31 | assertThat(base.getParameter("p1")).isNotNull(); 32 | assertThat(base.getParameter("p2")).isNotNull(); 33 | assertThat(base.getParameter("p3")).isNotNull(); 34 | assertThat(base.getParameter("p4")).isNotNull(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/dsl/ExecutionModelTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.core.platform.io.RuntimeEventProvider; 5 | import com.xatkit.dsl.intent.IntentVar; 6 | import com.xatkit.dsl.library.LibraryProvider; 7 | import com.xatkit.dsl.state.StateVar; 8 | import com.xatkit.execution.ExecutionModel; 9 | import lombok.val; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | 13 | import static com.xatkit.dsl.DSL.intent; 14 | import static com.xatkit.dsl.DSL.library; 15 | import static com.xatkit.dsl.DSL.model; 16 | import static com.xatkit.dsl.DSL.state; 17 | import static org.assertj.core.api.Assertions.assertThat; 18 | import static org.mockito.Mockito.mock; 19 | 20 | public class ExecutionModelTest { 21 | 22 | private StateVar s1; 23 | 24 | private StateVar s2; 25 | 26 | private IntentVar i1; 27 | 28 | private IntentVar i2; 29 | 30 | private LibraryProvider library; 31 | 32 | private RuntimePlatform platform = mock(RuntimePlatform.class); 33 | 34 | private RuntimeEventProvider provider = mock(RuntimeEventProvider.class); 35 | 36 | @Before 37 | public void setUp() { 38 | i1 = intent("Intent1") 39 | .trainingSentence("Hello"); 40 | 41 | i2 = intent("Intent2") 42 | .trainingSentence("Bye"); 43 | 44 | s1 = state("S1"); 45 | s2 = state("S2"); 46 | 47 | s1 48 | .body(c -> System.out.println("S1 body")) 49 | .next() 50 | .moveTo(s2); 51 | s2 52 | .body(c -> System.out.println("S2 body")) 53 | .next() 54 | .moveTo(s1); 55 | 56 | library = library("Library") 57 | .intent(i1) 58 | .intent(i2); 59 | 60 | } 61 | 62 | @Test 63 | public void createModelWithIntents() { 64 | val model = model() 65 | .useEvent(i1) 66 | .useEvent(i2) 67 | .listenTo(provider) 68 | .initState(s1) 69 | .defaultFallbackState(s2); 70 | 71 | ExecutionModel base = model.getExecutionModel(); 72 | assertThat(base.getUsedEvents()).hasSize(2); 73 | assertThat(base.getUsedEvents()).anyMatch(e -> e.getName().equals("Intent1")); 74 | assertThat(base.getUsedEvents()).anyMatch(e -> e.getName().equals("Intent2")); 75 | } 76 | 77 | @Test 78 | public void createModelWithLibrary() { 79 | val model = model() 80 | .useIntents(library) 81 | .listenTo(provider) 82 | .initState(s1) 83 | .defaultFallbackState(s2); 84 | 85 | ExecutionModel base = model.getExecutionModel(); 86 | assertThat(base.getUsedEvents()).hasSize(2); 87 | assertThat(base.getUsedEvents()).anyMatch(e -> e.getName().equals("Intent1")); 88 | assertThat(base.getUsedEvents()).anyMatch(e -> e.getName().equals("Intent2")); 89 | } 90 | 91 | @Test 92 | public void createModelWithStates() { 93 | val model = model() 94 | .listenTo(provider) 95 | .useState(s1) 96 | .useState(s2) 97 | .initState(s1) 98 | .defaultFallbackState(s2); 99 | 100 | ExecutionModel base = model.getExecutionModel(); 101 | assertThat(base.getStates()).hasSize(2); 102 | assertThat(base.getStates()).anyMatch(s -> s.getName().equals("S1")); 103 | assertThat(base.getStates()).anyMatch(s -> s.getName().equals("S2")); 104 | } 105 | 106 | @Test 107 | public void createModelWithPlatform() { 108 | val model = model() 109 | .usePlatform(platform) 110 | .listenTo(provider) 111 | .initState(s1) 112 | .defaultFallbackState(s2); 113 | 114 | ExecutionModel base = model.getExecutionModel(); 115 | assertThat(base.getUsedPlatforms()).hasSize(1); 116 | assertThat(base.getUsedPlatforms()).contains(platform); 117 | } 118 | 119 | @Test 120 | public void createModelWithProvider() { 121 | val model = model() 122 | .listenTo(provider) 123 | .initState(s1) 124 | .defaultFallbackState(s2); 125 | 126 | ExecutionModel base = model.getExecutionModel(); 127 | assertThat(base.getUsedProviders()).hasSize(1); 128 | assertThat(base.getUsedProviders()).contains(provider); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/dsl/IntentTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl; 2 | 3 | import com.xatkit.intent.ContextParameter; 4 | import com.xatkit.intent.IntentDefinition; 5 | import lombok.val; 6 | import org.junit.Test; 7 | 8 | import static com.xatkit.dsl.DSL.city; 9 | import static com.xatkit.dsl.DSL.intent; 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | public class IntentTest { 13 | 14 | @Test 15 | public void intentWithTrainingSentences() { 16 | val intent = intent("Greetings") 17 | .trainingSentence("Greetings") 18 | .trainingSentence("Hi") 19 | .trainingSentence("Hello"); 20 | 21 | IntentDefinition base = intent.getIntentDefinition(); 22 | assertThat(base.getName()).isEqualTo("Greetings"); 23 | assertThat(base.getTrainingSentences()).hasSize(3); 24 | assertThat(base.getTrainingSentences()).contains("Greetings", "Hi", "Hello"); 25 | } 26 | 27 | @Test 28 | public void intentWithParameter() { 29 | val intent = intent("LiveIn") 30 | .trainingSentence("I live in Barcelona") 31 | .parameter("cityName") 32 | .fromFragment("Barcelona") 33 | .entity(city()); 34 | 35 | IntentDefinition base = intent.getIntentDefinition(); 36 | assertThat(base.getTrainingSentences()).hasSize(1); 37 | assertThat(base.getTrainingSentences()).contains("I live in Barcelona"); 38 | assertThat(base.getParameters()).hasSize(1); 39 | ContextParameter parameter1 = base.getParameters().get(0); 40 | assertThat(parameter1.getName()).isEqualTo("cityName"); 41 | assertThat(parameter1.getTextFragments()).contains("Barcelona"); 42 | assertThat(parameter1.getEntity().getReferredEntity().getName()).isEqualTo(city().getReferredEntity().getName()); 43 | } 44 | 45 | @Test 46 | public void intentWithParameterMultipleFragments() { 47 | val intent = intent("LiveIn") 48 | .trainingSentence("I live in Barcelona") 49 | .trainingSentence("I am from Paris") 50 | .parameter("cityName") 51 | .fromFragment("Barcelona", "Paris") 52 | .entity(city()); 53 | 54 | IntentDefinition base = intent.getIntentDefinition(); 55 | assertThat(base.getTrainingSentences()).hasSize(2); 56 | assertThat(base.getTrainingSentences()).contains("I live in Barcelona", "I am from Paris"); 57 | assertThat(base.getParameters()).hasSize(1); 58 | ContextParameter parameter1 = base.getParameters().get(0); 59 | assertThat(parameter1.getName()).isEqualTo("cityName"); 60 | assertThat(parameter1.getTextFragments()).contains("Barcelona", "Paris"); 61 | assertThat(parameter1.getEntity().getReferredEntity().getName()).isEqualTo(city().getReferredEntity().getName()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/dsl/LibraryTest.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.dsl; 2 | 3 | import com.xatkit.intent.CompositeEntityDefinition; 4 | import com.xatkit.intent.Library; 5 | import com.xatkit.intent.MappingEntityDefinition; 6 | import lombok.val; 7 | import org.junit.Test; 8 | 9 | import static com.xatkit.dsl.DSL.composite; 10 | import static com.xatkit.dsl.DSL.intent; 11 | import static com.xatkit.dsl.DSL.library; 12 | import static com.xatkit.dsl.DSL.mapping; 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | 15 | public class LibraryTest { 16 | 17 | @Test 18 | public void libraryWithIntents() { 19 | val library = library("Library") 20 | .intent(intent("Greetings") 21 | .trainingSentence("Hello") 22 | .trainingSentence("Hi") 23 | ) 24 | .intent(intent("Bye") 25 | .trainingSentence("Bye") 26 | ); 27 | 28 | Library base = library.getLibrary(); 29 | assertThat(base.getName()).isEqualTo("Library"); 30 | assertThat(base.getEventDefinitions()).hasSize(2); 31 | assertThat(base.getEventDefinitions()).anyMatch(e -> e.getName().equals("Greetings")); 32 | assertThat(base.getEventDefinitions()).anyMatch(e -> e.getName().equals("Bye")); 33 | } 34 | 35 | @Test 36 | public void libraryWithEntities() { 37 | val library = library("Library") 38 | .entity(mapping("Mapping") 39 | .entry() 40 | .value("Value1").synonym("Synonym1") 41 | ) 42 | .entity(composite("Composite") 43 | .entry() 44 | .text("text1").text("text2") 45 | ); 46 | 47 | Library base = library.getLibrary(); 48 | assertThat(base.getName()).isEqualTo("Library"); 49 | assertThat(base.getCustomEntities()).hasSize(2); 50 | assertThat(base.getCustomEntities()).anyMatch(e -> (e instanceof MappingEntityDefinition) && e.getName().equals("Mapping")); 51 | assertThat(base.getCustomEntities()).anyMatch(e -> (e instanceof CompositeEntityDefinition) && e.getName().equals("Composite")); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/EmptyRuntimePlatform.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | 5 | /** 6 | * An empty {@link RuntimePlatform} used to test {@link RuntimePlatform}-related methods. 7 | */ 8 | public class EmptyRuntimePlatform extends RuntimePlatform { 9 | 10 | public EmptyRuntimePlatform() { 11 | super(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/StubRuntimePlatform.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.stubs.action.ErroringStubRuntimeAction; 5 | import com.xatkit.stubs.action.StubRuntimeAction; 6 | 7 | public class StubRuntimePlatform extends RuntimePlatform { 8 | 9 | private StubRuntimeAction runtimeAction; 10 | 11 | private ErroringStubRuntimeAction erroringRuntimeAction; 12 | 13 | public StubRuntimePlatform() { 14 | init(); 15 | } 16 | 17 | public void init() { 18 | this.runtimeAction = new StubRuntimeAction(this); 19 | this.erroringRuntimeAction = new ErroringStubRuntimeAction(this); 20 | } 21 | 22 | public StubRuntimeAction getAction() { 23 | return runtimeAction; 24 | } 25 | 26 | public ErroringStubRuntimeAction getErroringAction() { 27 | return erroringRuntimeAction; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/StubXatkitServer.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs; 2 | 3 | import com.xatkit.core.server.HttpMethod; 4 | import com.xatkit.core.server.RestHandlerException; 5 | import com.xatkit.core.server.XatkitServer; 6 | import org.apache.commons.configuration2.BaseConfiguration; 7 | import org.apache.http.Header; 8 | import org.apache.http.NameValuePair; 9 | 10 | import javax.annotation.Nullable; 11 | import java.util.List; 12 | 13 | public class StubXatkitServer extends XatkitServer { 14 | 15 | private HttpMethod lastIsRestEndpointMethod; 16 | 17 | private String lastIsRestEndpointURI; 18 | 19 | private HttpMethod lastNotifyRestHandlerMethod; 20 | 21 | private String lastNotifyRestHandlerURI; 22 | 23 | private List

lastNotifyRestHandlerHeaders; 24 | 25 | private List lastNotifyRestHandlerParams; 26 | 27 | private Object lastNotifyRestHandlerContent; 28 | 29 | private String lastNotifyRestHandlerContentType; 30 | 31 | public StubXatkitServer() { 32 | super(new BaseConfiguration()); 33 | } 34 | 35 | @Override 36 | public boolean isRestEndpoint(HttpMethod httpMethod, String uri) { 37 | this.lastIsRestEndpointMethod = httpMethod; 38 | this.lastIsRestEndpointURI = uri; 39 | return super.isRestEndpoint(httpMethod, uri); 40 | } 41 | 42 | @Override 43 | public Object notifyRestHandler(HttpMethod httpMethod, String uri, List
headers, List params, 44 | @Nullable Object content, String contentType) throws RestHandlerException { 45 | this.lastNotifyRestHandlerMethod = httpMethod; 46 | this.lastNotifyRestHandlerURI = uri; 47 | this.lastNotifyRestHandlerHeaders = headers; 48 | this.lastNotifyRestHandlerParams = params; 49 | this.lastNotifyRestHandlerContent = content; 50 | this.lastNotifyRestHandlerContentType = contentType; 51 | return super.notifyRestHandler(httpMethod, uri, headers, params, content, contentType); 52 | } 53 | 54 | public HttpMethod getLastIsRestEndpointMethod() { 55 | return this.lastIsRestEndpointMethod; 56 | } 57 | 58 | public String getLastIsRestEndpointURI() { 59 | return this.lastIsRestEndpointURI; 60 | } 61 | 62 | public HttpMethod getLastNotifyRestHandlerMethod() { 63 | return this.lastNotifyRestHandlerMethod; 64 | } 65 | 66 | public String getLastNotifyRestHandlerURI() { 67 | return this.lastNotifyRestHandlerURI; 68 | } 69 | 70 | public List
getLastNotifyRestHandlerHeaders() { 71 | return this.lastNotifyRestHandlerHeaders; 72 | } 73 | 74 | public List getLastNotifyRestHandlerParams() { 75 | return this.lastNotifyRestHandlerParams; 76 | } 77 | 78 | public Object getLastNotifyRestHandlerContent() { 79 | return this.lastNotifyRestHandlerContent; 80 | } 81 | 82 | public String getLastNotifyRestHandlerContentType() { 83 | return this.lastNotifyRestHandlerContentType; 84 | } 85 | 86 | public void clean() { 87 | this.lastIsRestEndpointMethod = null; 88 | this.lastIsRestEndpointURI = null; 89 | this.lastNotifyRestHandlerMethod = null; 90 | this.lastNotifyRestHandlerURI = null; 91 | this.lastNotifyRestHandlerHeaders = null; 92 | this.lastNotifyRestHandlerParams = null; 93 | this.lastNotifyRestHandlerContent = null; 94 | this.lastNotifyRestHandlerContentType = null; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/TestingStateContextFactory.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs; 2 | 3 | import com.xatkit.execution.StateContext; 4 | import lombok.NonNull; 5 | 6 | /** 7 | * Creates instances of {@link TestingStateContext} from {@link StateContext} instances. 8 | *

9 | * This factory is typically used to wrap a {@link StateContext} created by an 10 | * {@link com.xatkit.core.recognition.IntentRecognitionProvider} into a {@link TestingStateContext} that provides 11 | * additional methods to customize the intents that can be matched by the provider. 12 | *

13 | * Using {@link TestingStateContext}s allows to quickly create valid {@link StateContext} instances with a given set 14 | * of intents enabled (as if they were part of the current state's transitions). This shorten intent provider test 15 | * cases as they don't require a valid bot model anymore. 16 | *

17 | * Usage Example 18 | *

19 |  * {@code
20 |  * IntentRecognitionProvider provider = getProvider();
21 |  * StateContext baseContext = provider.createContext("myContext");
22 |  * TestingStateContext testingContext = TestingStateContextFactory.wrap(baseContext);
23 |  * testingContext.enableIntent(myIntent);
24 |  * provider.getIntent("input", testingContext);
25 |  * // check the result
26 |  * }
27 |  * 
28 | */ 29 | public class TestingStateContextFactory { 30 | 31 | public TestingStateContextFactory() { 32 | 33 | } 34 | 35 | /** 36 | * Wraps the provided {@code stateContext} into a {@link TestingStateContext}. 37 | * 38 | * @param stateContext the {@link StateContext} to wrap 39 | * @return the created {@link TestingStateContext} 40 | * @throws NullPointerException if the provided {@code stateContext} is {@code null} 41 | */ 42 | public TestingStateContext wrap(@NonNull StateContext stateContext) { 43 | return new TestingStateContext(stateContext); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/action/ErroringStubRuntimeAction.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs.action; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.core.platform.action.RuntimeAction; 5 | import com.xatkit.execution.ExecutionFactory; 6 | import com.xatkit.execution.StateContext; 7 | 8 | public class ErroringStubRuntimeAction extends RuntimeAction { 9 | 10 | private boolean actionProcessed; 11 | 12 | private static StateContext getStateContext() { 13 | StateContext context = ExecutionFactory.eINSTANCE.createStateContext(); 14 | context.setContextId("id"); 15 | return context; 16 | } 17 | 18 | public ErroringStubRuntimeAction(RuntimePlatform runtimePlatform) { 19 | super(runtimePlatform, getStateContext()); 20 | } 21 | 22 | public boolean isActionProcessed() { 23 | return actionProcessed; 24 | } 25 | 26 | @Override 27 | public Object compute() { 28 | this.actionProcessed = true; 29 | throw new RuntimeException("Error when running the action"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/action/StubRuntimeAction.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs.action; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.core.platform.action.RuntimeAction; 5 | import com.xatkit.execution.ExecutionFactory; 6 | import com.xatkit.execution.StateContext; 7 | 8 | public class StubRuntimeAction extends RuntimeAction { 9 | 10 | private boolean actionProcessed; 11 | 12 | private static StateContext getStateContext() { 13 | StateContext context = ExecutionFactory.eINSTANCE.createStateContext(); 14 | context.setContextId("id"); 15 | return context; 16 | } 17 | 18 | public StubRuntimeAction(RuntimePlatform runtimePlatform) { 19 | super(runtimePlatform, getStateContext()); 20 | } 21 | 22 | public boolean isActionProcessed() { 23 | return actionProcessed; 24 | } 25 | 26 | @Override 27 | public Object compute() { 28 | this.actionProcessed = true; 29 | return null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/action/StubRuntimeActionNoParameter.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs.action; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.core.platform.action.RuntimeAction; 5 | import com.xatkit.execution.StateContext; 6 | 7 | public class StubRuntimeActionNoParameter extends RuntimeAction { 8 | 9 | public StubRuntimeActionNoParameter(RuntimePlatform runtimePlatform, StateContext context) { 10 | super(runtimePlatform, context); 11 | } 12 | 13 | @Override 14 | public Object compute() { 15 | return null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/action/StubRuntimeActionTwoConstructors.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs.action; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.core.platform.action.RuntimeAction; 5 | import com.xatkit.execution.StateContext; 6 | 7 | import java.util.List; 8 | 9 | public class StubRuntimeActionTwoConstructors extends RuntimeAction { 10 | 11 | private String param; 12 | 13 | private List listParam; 14 | 15 | public StubRuntimeActionTwoConstructors(RuntimePlatform runtimePlatform, StateContext context, String param) { 16 | super(runtimePlatform, context); 17 | this.param = param; 18 | } 19 | 20 | public StubRuntimeActionTwoConstructors(RuntimePlatform runtimePlatform, StateContext context, List 21 | listParam) { 22 | super(runtimePlatform, context); 23 | this.listParam = listParam; 24 | } 25 | 26 | public String getParam() { 27 | return this.param; 28 | } 29 | 30 | public List getListParam() { 31 | return this.listParam; 32 | } 33 | 34 | @Override 35 | public Object compute() { 36 | return null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/action/StubRuntimeMessageAction.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs.action; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.core.platform.action.RuntimeMessageAction; 5 | import com.xatkit.execution.ExecutionFactory; 6 | import com.xatkit.execution.StateContext; 7 | import fr.inria.atlanmod.commons.log.Log; 8 | 9 | import java.util.UUID; 10 | 11 | public class StubRuntimeMessageAction extends RuntimeMessageAction { 12 | 13 | public static String RESULT = "result"; 14 | 15 | protected int attempts; 16 | 17 | private StateContext clientStateContext; 18 | 19 | public StubRuntimeMessageAction(RuntimePlatform runtimePlatform, StateContext context, String rawMessage) { 20 | super(runtimePlatform, context, rawMessage); 21 | this.clientStateContext = ExecutionFactory.eINSTANCE.createStateContext(); 22 | this.clientStateContext.setContextId(UUID.randomUUID().toString()); 23 | attempts = 0; 24 | } 25 | 26 | @Override 27 | protected Object compute() throws Exception { 28 | Log.info("Computing {0}, message stub: {1}", this.getClass().getSimpleName(), this.message); 29 | attempts++; 30 | return RESULT; 31 | } 32 | 33 | @Override 34 | protected StateContext getClientStateContext() { 35 | return clientStateContext; 36 | } 37 | 38 | public int getAttempts() { 39 | return attempts; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/action/StubRuntimeMessageActionIOException.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs.action; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.execution.StateContext; 5 | 6 | import java.io.IOException; 7 | 8 | public class StubRuntimeMessageActionIOException extends StubRuntimeMessageAction { 9 | 10 | public StubRuntimeMessageActionIOException(RuntimePlatform runtimePlatform, StateContext context, String 11 | rawMessage) { 12 | super(runtimePlatform, context, rawMessage); 13 | } 14 | 15 | @Override 16 | protected Object compute() throws IOException { 17 | attempts++; 18 | throw new IOException("StubRuntimeMessageActionIOException"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/stubs/action/StubRuntimeMessageActionIOExceptionThenOk.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.stubs.action; 2 | 3 | import com.xatkit.core.platform.RuntimePlatform; 4 | import com.xatkit.execution.StateContext; 5 | 6 | import java.io.IOException; 7 | 8 | public class StubRuntimeMessageActionIOExceptionThenOk extends StubRuntimeMessageAction { 9 | 10 | public StubRuntimeMessageActionIOExceptionThenOk(RuntimePlatform runtimePlatform, StateContext context, String 11 | rawMessage) { 12 | super(runtimePlatform, context, rawMessage); 13 | } 14 | 15 | @Override 16 | protected Object compute() throws IOException { 17 | attempts++; 18 | if(attempts == 1) { 19 | throw new IOException("StubRuntimeMessageActionIOException"); 20 | } else { 21 | return RESULT; 22 | } 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/test/bot/TestBot.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.test.bot; 2 | 3 | import com.xatkit.core.platform.io.RuntimeEventProvider; 4 | import com.xatkit.dsl.DSL; 5 | import com.xatkit.execution.ExecutionModel; 6 | import com.xatkit.intent.IntentFactory; 7 | import com.xatkit.intent.RecognizedIntent; 8 | import lombok.Data; 9 | import lombok.val; 10 | 11 | import static com.xatkit.dsl.DSL.fallbackState; 12 | import static com.xatkit.dsl.DSL.intent; 13 | import static com.xatkit.dsl.DSL.intentIs; 14 | import static com.xatkit.dsl.DSL.state; 15 | import static org.mockito.Mockito.mock; 16 | 17 | @Data 18 | public class TestBot { 19 | 20 | private RecognizedIntent navigableIntent; 21 | 22 | private RecognizedIntent notNavigableIntent; 23 | 24 | private boolean greetingsStateBodyExecuted; 25 | 26 | private boolean defaultFallbackExecuted; 27 | 28 | private boolean sessionCheckedBodyExecuted; 29 | 30 | private ExecutionModel model; 31 | 32 | private RuntimeEventProvider provider = mock(RuntimeEventProvider.class); 33 | 34 | public TestBot() { 35 | this.greetingsStateBodyExecuted = false; 36 | this.defaultFallbackExecuted = false; 37 | this.sessionCheckedBodyExecuted = false; 38 | val greetings = intent("Greetings") 39 | .trainingSentence("Hi"); 40 | 41 | val init = state("Init"); 42 | val greetingsState = state("GreetingsState"); 43 | val sessionCheckedState = state("SessionChecked"); 44 | 45 | init 46 | .next() 47 | .when(intentIs(greetings)).moveTo(greetingsState) 48 | .when(stateContext -> stateContext.getSession().containsKey("key")).moveTo(sessionCheckedState); 49 | 50 | greetingsState 51 | .body(context -> greetingsStateBodyExecuted = true) 52 | .next() 53 | .moveTo(init); 54 | 55 | sessionCheckedState 56 | .body(context -> { 57 | /* 58 | * Remove the key otherwise we have an infinite loop between Init and SessionChecked. 59 | */ 60 | context.getSession().remove("key"); 61 | sessionCheckedBodyExecuted = true; 62 | }) 63 | .next() 64 | .moveTo(init); 65 | 66 | val fallback = fallbackState() 67 | .body(context -> defaultFallbackExecuted = true); 68 | 69 | model = DSL.model() 70 | .listenTo(provider) 71 | .initState(init) 72 | .defaultFallbackState(fallback) 73 | .getExecutionModel(); 74 | 75 | navigableIntent = IntentFactory.eINSTANCE.createRecognizedIntent(); 76 | navigableIntent.setDefinition(greetings.getIntentDefinition()); 77 | 78 | val unmatchedIntentDefinition = intent("Unmatched") 79 | .trainingSentence("Unmatched"); 80 | notNavigableIntent = IntentFactory.eINSTANCE.createRecognizedIntent(); 81 | notNavigableIntent.setDefinition(unmatchedIntentDefinition.getIntentDefinition()); 82 | } 83 | 84 | public void reset() { 85 | this.greetingsStateBodyExecuted = false; 86 | this.defaultFallbackExecuted = false; 87 | this.sessionCheckedBodyExecuted = false; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/com/xatkit/test/util/VariableLoaderHelper.java: -------------------------------------------------------------------------------- 1 | package com.xatkit.test.util; 2 | 3 | import org.apache.commons.configuration2.PropertiesConfiguration; 4 | import org.apache.commons.configuration2.ex.ConfigurationException; 5 | 6 | import java.io.FileInputStream; 7 | import java.io.FileNotFoundException; 8 | import java.io.IOException; 9 | import java.io.InputStreamReader; 10 | import java.io.Reader; 11 | import java.net.URL; 12 | import java.text.MessageFormat; 13 | 14 | import static java.util.Objects.isNull; 15 | 16 | /** 17 | * An utility class to load test-related variables. 18 | *

19 | * This class loads the variables from the {@code test-variables.properties} configuration file located in {@code 20 | * /src/test/resources}. This file is not pushed in the Github repository. If you want to test Xatkit you'll need to 21 | * create your own version of the file with the following properties: 22 | *

23 |  * {@code
24 |  * xatkit.dialogflow.projectId = 
25 |  * xatkit.dialogflow.credentials.path = 
26 |  * xatkit.dialogflow.language = 
27 |  * xatkit.perspectiveapi.apiKey = 
28 |  * xatkit.nlpjs.agentId = 
29 |  * xatkit.nlpjs.server = 
30 |  * xatkit.nlpjs.basicauth.username = 
31 |  * xatkit.nlpjs.basicauth.password = 
32 |  * }
33 |  * 
34 | * You'll also need to add your own DialogFlow credentials file in {@code /src/test/resources} named according to 35 | * your {@code xatkit.dialogflow.credentials.path} property. 36 | *

37 | * Note: if you are part of Xatkit you can get in touch with us to get credentials to run your tests. 38 | */ 39 | public class VariableLoaderHelper { 40 | 41 | private static String LOCAL_FILE_PATH = "test-variables.properties"; 42 | 43 | public static String getVariable(String key) { 44 | URL resource = VariableLoaderHelper.class.getClassLoader().getResource(LOCAL_FILE_PATH); 45 | if (isNull(resource)) { 46 | throw new RuntimeException(MessageFormat.format("Cannot retrieve Xatkit bot variables from local " + 47 | "file: the file {0} does not exist", LOCAL_FILE_PATH)); 48 | } 49 | String fileString = resource.getFile(); 50 | FileInputStream fileInputStream; 51 | try { 52 | fileInputStream = new FileInputStream(fileString); 53 | } catch (FileNotFoundException e) { 54 | throw new RuntimeException(e); 55 | } 56 | Reader reader = new InputStreamReader(fileInputStream); 57 | PropertiesConfiguration configuration = new PropertiesConfiguration(); 58 | try { 59 | configuration.read(reader); 60 | } catch (ConfigurationException | IOException e) { 61 | throw new RuntimeException(e); 62 | } 63 | return configuration.getString(key); 64 | } 65 | } -------------------------------------------------------------------------------- /src/test/resources/empty-configuration.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xatkit-bot-platform/xatkit-runtime/e87b01457e18e1d3b60d9b7238fb21fa94b29aed/src/test/resources/empty-configuration.properties -------------------------------------------------------------------------------- /src/test/resources/log4j2-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | %d{yyyy-MM-dd HH:mm:ss} %-5p %m%n 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/test/resources/test-variables-empty.properties: -------------------------------------------------------------------------------- 1 | xatkit.dialogflow.projectId = 2 | xatkit.dialogflow.language = 3 | xatkit.dialogflow.credentials.path = 4 | xatkit.perspectiveapi.apiKey = 5 | xatkit.nlpjs.agentId = 6 | xatkit.nlpjs.server = 7 | xatkit.nlpjs.basicauth.username = 8 | xatkit.nlpjs.basicauth.password = -------------------------------------------------------------------------------- /src/test/resources/xatkit-secrets.zip.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xatkit-bot-platform/xatkit-runtime/e87b01457e18e1d3b60d9b7238fb21fa94b29aed/src/test/resources/xatkit-secrets.zip.gpg --------------------------------------------------------------------------------