Are you ready to write your first openQA plug-in?

Below you will find three practical examples showing how you can use openQA framework.

All the examples are available in examples project.

In this example we show how to instantiate and run the framework over code. We also show how to implement an interpreter module for chat.

1) Download the openQA engine end HelloWorld project.

2) Copy both projects to the same directory.

3) Execute the follow command in the same directory:

java -cp "*" org.aksw.openqa.examples.example1.HelloWorldMain "hi"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package org.aksw.openqa.examples.example1;

import java.util.List;

import org.aksw.openqa.Properties;
import org.aksw.openqa.component.object.IResult;
import org.aksw.openqa.main.QAEngineProcessor;
import org.aksw.openqa.main.QueryResult;
import org.aksw.openqa.manager.plugin.PluginManager;

public class HelloWorldMain {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		String question = "How are you";
		String answer = "";
		if(args.length > 0)
			question  = args[0];
		
		System.out.println("You:\t" + question);
		    	    	
    	HelloWorldInterpreter interpreter = new HelloWorldInterpreter();
    	
    	PluginManager pluginManager = new PluginManager();
    	pluginManager.register(interpreter);
    	pluginManager.setActive(true, interpreter.getId());
    	
    	QAEngineProcessor queryProcessor = new QAEngineProcessor(pluginManager);
    	
    	QueryResult result;
		result = queryProcessor.process(question);
		List<? extends IResult> output = result.getOutput();
		if(output.size() > 0)
			answer = output.get(0).getProperty(Properties.Literal.TEXT, String.class);
		
		System.out.println("openQA:\t" + answer);		
	}
}
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package org.aksw.openqa.examples.example1;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.aksw.openqa.Properties;
import org.aksw.openqa.component.answerformulation.AbstractInterpreter;
import org.aksw.openqa.component.context.Context;
import org.aksw.openqa.component.object.IParam;
import org.aksw.openqa.component.object.IResult;
import org.aksw.openqa.component.object.Result;
import org.aksw.openqa.component.providers.impl.ServiceProvider;

public class HelloWorldInterpreter extends AbstractInterpreter {
	
	String[][] openQA= {
			// standard greetings
			{"hi", "hello", "hola", "ola", "howdy"},
			{"hi", "hello", "hey"},
			// question greetings
			{"how are you", "how r you", "how r u", "how are u"},
			{"good", "doing well", "hey"},
			// default
			{"shut up", "you're bad", "noob", "stop talking", "openQA is unavailable, due to LOL"}
	};
	
	public HelloWorldInterpreter() {
		super(null /* there is no params to be passed */);
	}

	public HelloWorldInterpreter(Map<String, Object> params) {
		super(params);
	}
	
	@Override
	public String getVersion() {
		return "example1"; // version
	}
	
	@Override
	public String getLabel() {
		return "HelloWorldInterpreter"; // the label
	}
	
	@Override
	public String getId() {
		return getLabel() + " " + getVersion(); // id = label + version
	}
	
	@Override
	public boolean canProcess(IParam param) {
		return param.contains(Properties.Literal.TEXT);
	}

	@Override
	public List<? extends IResult> process(IParam param,
			ServiceProvider services, Context context) throws Exception {
		
		String you = (String) param.getProperty(Properties.Literal.TEXT);	
		String answer = "";

		int response = 0; // default response 2
		
		if(!you.isEmpty()) {
		
			// eliminating white spaces
			you.trim();
			
			// removing punctuation (.,!,?)
			while(
					you.charAt(you.length()-1) == '.' ||
					you.charAt(you.length()-1) == '!' ||
					you.charAt(you.length()-1) == '?'
					) {
				you = you.substring(0, you.length()-1);
			}
			
			// eliminating white spaces, again :)
			you.trim();
			while(((response*2)+1)< openQA.length) {
				// always check the questions from the position j*2 of the openQA matrix
				if(inArray(you.toLowerCase(), openQA[response*2])) {
					// get one of the answers from the position j*2+1 of the matched questions
					int r = (int) Math.floor(Math.random() *  openQA[(response*2)+1].length);
					
					// print the answer
					answer = openQA[(response*2)+1][r];
					break; // interrupt the interaction
				}
				response++; // check next group of questions
			}
		} else
			response = 2;
		
		if(response == 2) { // if we did not find any math, answer default answers
			// get one of the answers from the position j*2+1 of the matched questions
			int r = (int) Math.floor(Math.random() *  openQA[(response*2)].length);
			
			// print the answer
			answer = openQA[response*2][r];
		}
		
		List<IResult> results = new ArrayList<>();
		Result result = new Result();
		result.setProperty(Properties.Literal.TEXT, answer);
		results.add(result);
		
		return results; // since we already consume the parameter, return null
	}
	
	/**
	 * Return true if there is any sentence in the array that match the given input 
	 * string or false otherwise.
	 * 
	 * @param in input string.
	 * @param str an array containing am array of sentences (questions).
	 * @return true if there is any sentence in the array that match the given input string.
	 */
	private boolean inArray(String in, String[] str) {
		for(int i = 0;i<str.length;i++) {
			if(str[i].equals(in))
				return true;
		}		
		return false;
	}
}

In this example we extend the example 1, moving the code of the answers to an retriever module.

1) Download the openQA engine end HelloWorld project.

2) Copy both projects to the same directory.

3) Execute the follow command in the same directory:

java -cp "*" org.aksw.openqa.examples.example2.HelloWorldMain "Hello"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package org.aksw.openqa.examples.example2;

import java.util.List;

import org.aksw.openqa.Properties;
import org.aksw.openqa.component.object.IResult;
import org.aksw.openqa.main.QAEngineProcessor;
import org.aksw.openqa.main.QueryResult;
import org.aksw.openqa.manager.plugin.PluginManager;

public class HelloWorldMain {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		String question = "";
		String answer = "";
		if(args.length > 0)
			question  = args[0];
		
		System.out.println("You:\t" + question);
		   	    	
    	HelloWorldInterpreter interpreter = new HelloWorldInterpreter();
    	HelloWorldRetriever retriever = new HelloWorldRetriever();
    	
    	PluginManager pluginManager = new PluginManager();
    	pluginManager.register(interpreter);
    	pluginManager.register(retriever);
    	pluginManager.setActive(true, interpreter.getId());
    	pluginManager.setActive(true, retriever.getId());
    	
    	QAEngineProcessor queryProcessor = new QAEngineProcessor(pluginManager);
    	
    	QueryResult result;
		result = queryProcessor.process(question);
		List<? extends IResult> output = result.getOutput();
		if(output.size() > 0)
			answer = output.get(0).getProperty(Properties.Literal.TEXT, String.class);
		
		System.out.println("openQA:\t" + answer);
		
	}

}
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package org.aksw.openqa.examples.example2;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.aksw.openqa.Properties;
import org.aksw.openqa.component.answerformulation.AbstractInterpreter;
import org.aksw.openqa.component.context.Context;
import org.aksw.openqa.component.object.IParam;
import org.aksw.openqa.component.object.IResult;
import org.aksw.openqa.component.object.Result;
import org.aksw.openqa.component.providers.impl.ServiceProvider;
import org.aksw.openqa.examples.HelloWorldParameters;

public class HelloWorldInterpreter extends AbstractInterpreter {
	
	String[][] allwedQuestions= {
			// standard greetings
			{"hi", "hello", "hola", "ola", "howdy"},
			// question greetings
			{"how are you", "how r you", "how r u", "how are u"}
	};
	
	public HelloWorldInterpreter() {
		super(null /* there is no params to be passed */);
	}

	public HelloWorldInterpreter(Map<String, Object> params) {
		super(params);
	}
	
	@Override
	public String getVersion() {
		return "example2"; // version
	}
	
	@Override
	public String getLabel() {
		return "HelloWorldInterpreter"; // the label
	}
	
	@Override
	public String getId() {
		return getLabel() + " " + getVersion(); // id = label + version
	}
	
	@Override
	public boolean canProcess(IParam param) {
		return param.contains(Properties.Literal.TEXT, String.class);
	}

	@Override
	public List<? extends IResult> process(IParam param,
			ServiceProvider services, Context context) throws Exception {
		
		String you = param.getProperty(Properties.Literal.TEXT, String.class);
		
		Integer response = 0;
		
		if(!you.isEmpty()) {
		
			// eliminating white spaces
			you.trim();
			
			// removing punctuation (.,!,?)
			while(
					you.charAt(you.length()-1) == '.' ||
					you.charAt(you.length()-1) == '!' ||
					you.charAt(you.length()-1) == '?'
					) {
				you = you.substring(0, you.length()-1);
			}
			
			// eliminating white spaces, again :)
			you.trim();
			
			int j = 0;
			while(response==0) {
				// always check the questions from the position j*2 of the allowedQuestions matrix
				if(inArray(you.toLowerCase(), allwedQuestions[j])) {
					response = j;
					break;
				}
				j++; // check next group of questions
				
				// check if the allowed questions vector is finished
				if(j*2==(allwedQuestions.length-1) && response == 0) {
					response = j; // if it is, we did not find any match
				}
			}
		} else
			response = 2; // end of matrix
		
		List<IResult> results = new ArrayList<>();
		Result result = new Result();
		result.setProperty(HelloWorldParameters.Property.MATRIX_LINE, response);
		results.add(result);
		
		return results; // since we already consume the parameter, return null
	}
	
	/**
	 * Return true if there is any sentence in the array that match the given input 
	 * string or false otherwise.
	 * 
	 * @param in input string.
	 * @param str an array containing am array of sentences (questions).
	 * @return true if there is any sentence in the array that match the given input string.
	 */
	private boolean inArray(String in, String[] str) {
		for(int i = 0;i<str.length;i++) {
			if(str[i].equals(in))
				return true;
		}		
		return false;
	}


}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package org.aksw.openqa.examples.example2;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.aksw.openqa.Properties;
import org.aksw.openqa.component.answerformulation.AbstractRetriever;
import org.aksw.openqa.component.context.Context;
import org.aksw.openqa.component.object.IParam;
import org.aksw.openqa.component.object.IResult;
import org.aksw.openqa.component.object.Result;
import org.aksw.openqa.component.providers.impl.ServiceProvider;
import org.aksw.openqa.examples.HelloWorldParameters;

public class HelloWorldRetriever extends AbstractRetriever {

	String[][] answers= {
			// standard greetings
			{"hi", "hello", "hey"},
			// question greetings
			{"good", "doing well", "hey"},
			// default
			{"shut up", "you're bad", "noob", "stop talking", "openQA is unavailable, due to LOL"}
	};
	
	public HelloWorldRetriever() {
		super(null);
	}
	

	public HelloWorldRetriever(Map<String, Object> params) {
		super(params);
	}
	
	@Override
	public String getVersion() {
		return "example2"; // version
	}
	
	@Override
	public String getLabel() {
		return "HelloWorldRetriever"; // the label
	}

	@Override
	public boolean canProcess(IParam param) {
		// check if the argument have the required attribute
		return param.contains(HelloWorldParameters.Property.MATRIX_LINE, Integer.class);
	}

	@Override
	public List<? extends IResult> process(IParam param,
			ServiceProvider services, Context context) throws Exception {
		int respose = param.getProperty(HelloWorldParameters.Property.MATRIX_LINE, Integer.class);
		
		int r = (int) Math.floor(Math.random() *  answers[respose].length);
		
		// print the answer
		String answer = answers[respose][r];
		
		List<IResult> results = new ArrayList<>();
		Result result = new Result();
		result.setProperty(Properties.Literal.TEXT, answer);
		results.add(result);
		
		return results; // since we already consume the parameter, return null
	}
}

In this example we extend the example 2, now running the framework with the implemented service providers.

* Note that there is no need to set the label and version anymore, the framework is reading this information from the inf files in META-INF directory. There is also no need to setup the plug-ins, they will be automaticaly recovered under the registered interfaces (IInterpreterFactory and IRetrieverFactory) in META-INF/services directory.

When developing plug-ins is very important to keep the directory structure as follows.

org/aksw/openqa/examples/example3/HelloWorldMain.java
org/aksw/openqa/examples/example3/HelloWorldInterpreter.java
org/aksw/openqa/examples/example3/HelloWorldRetriever.java
...
META-INF/services/org.aksw.openqa.component.answerformulation.IInterpreterFactory
META-INF/services/org.aksw.openqa.component.answerformulation.IRetrieverFactory
META-INF/Manifest.mf
META-INF/org.aksw.openqa.examples.example3.HelloWorldInterpreter.inf
META-INF/org.aksw.openqa.examples.example3.HelloWorldRetriever.inf

1) Download the openQA engine and the Example project.

2) Put the Example project in a subdirectory (in our example openqa.example) directory called plugins.

3) Execute the follow command in the same directory:

ps: at the end you should have the following file structure:

./plugins/openqa.example/openqa.example.jar
./openqa.engine.jar

./java -jar openqa.engine.jar plugins "hi"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package org.aksw.openqa.examples.example3;

import java.util.List;

import org.aksw.openqa.Properties;
import org.aksw.openqa.component.object.IResult;
import org.aksw.openqa.main.QAEngineProcessor;
import org.aksw.openqa.main.QueryResult;
import org.aksw.openqa.manager.plugin.PluginManager;

public class HelloWorldMain {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		String question = "";
		String answer = "";
		if(args.length > 0)
			question  = args[0];
		
		System.out.println("You:\t" + question);
		
		ClassLoader contextClassLoader = HelloWorldMain.class.getClassLoader();    	
    	PluginManager pluginManager = new PluginManager(contextClassLoader);
    	pluginManager.setActive(true);
    	
    	QAEngineProcessor queryProcessor = new QAEngineProcessor(pluginManager);
    	
    	QueryResult result;
		result = queryProcessor.process(question);
		List<? extends IResult> output = result.getOutput();
		if(output.size() > 0)
			answer = output.get(0).getProperty(Properties.Literal.TEXT, String.class);
		
		System.out.println("openQA:\t" + answer);		
	}

}
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
package org.aksw.openqa.examples.example3;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.aksw.openqa.Properties;
import org.aksw.openqa.component.answerformulation.AbstractInterpreter;
import org.aksw.openqa.component.context.IContext;
import org.aksw.openqa.component.object.IParam;
import org.aksw.openqa.component.object.IResult;
import org.aksw.openqa.component.object.Result;
import org.aksw.openqa.component.providers.impl.ServiceProvider;
import org.aksw.openqa.examples.HelloWorldParameters;

public class HelloWorldInterpreter extends AbstractInterpreter {
	
	String[][] allwedQuestions= {
			// standard greetings
			{"hi", "hello", "hola", "ola", "howdy"},
			// question greetings
			{"how are you", "how r you", "how r u", "how are u"}
	};
	
	public HelloWorldInterpreter(Map<String, Object> params) {
		super(params);
	}
	
	@Override
	public boolean canProcess(IParam param) {
		return param.contains(Properties.Literal.TEXT, String.class);
	}

	@Override
	public List<? extends IResult> process(IParam param,
			ServiceProvider services, IContext context) throws Exception {
		
		String you = param.getProperty(Properties.Literal.TEXT, String.class);
		
		int response = 0;
		
		if(!you.isEmpty()) {
		
			// eliminating white spaces
			you.trim();
			
			// removing punctuation (.,!,?)
			while(
					you.charAt(you.length()-1) == '.' ||
					you.charAt(you.length()-1) == '!' ||
					you.charAt(you.length()-1) == '?'
					) {
				you = you.substring(0, you.length()-1);
			}
			
			// eliminating white spaces, again :)
			you.trim();
			
			int j = 0;
			while(response==0) {
				// always check the questions from the position j*2 of the allowedQuestions matrix
				if(inArray(you.toLowerCase(), allwedQuestions[j])) {
					response = j;
					break;
				}
				j++; // check next group of questions
				
				// check if the allowed questions vector is finished
				if(j*2==(allwedQuestions.length-1) && response == 0) {
					response = j; // if it is, we did not find any match
				}
			}
		} else
			response = 2; // end of matrix
		
		List<IResult> results = new ArrayList<>();
		Result result = new Result();
		HelloWorldParameter parameter = new HelloWorldParameter();
		parameter.setMatrixLine(response);
		result.setProperty(HelloWorldParameters.Property.MATRIX_LINE, parameter);
		results.add(result);
		
		return results; // since we already consume the parameter, return null
	}
	
	/**
	 * Return true if there is any sentence in the array that match the given input 
	 * string or false otherwise.
	 * 
	 * @param in input string.
	 * @param str an array containing am array of sentences (questions).
	 * @return true if there is any sentence in the array that match the given input string.
	 */
	private boolean inArray(String in, String[] str) {
		for(int i = 0;i<str.length;i++) {
			if(str[i].equals(in))
				return true;
		}		
		return false;
	}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package org.aksw.openqa.examples.example3;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.aksw.openqa.Properties;
import org.aksw.openqa.component.answerformulation.AbstractRetriever;
import org.aksw.openqa.component.context.IContext;
import org.aksw.openqa.component.object.IParam;
import org.aksw.openqa.component.object.IResult;
import org.aksw.openqa.component.object.Result;
import org.aksw.openqa.component.providers.impl.ServiceProvider;
import org.aksw.openqa.examples.HelloWorldParameters;

public class HelloWorldRetriever extends AbstractRetriever {

	String[][] answers= {
			// standard greetings
			{"hi", "hello", "hey"},
			// question greetings
			{"good", "doing well", "hey"},
			// default
			{"shut up", "you're bad", "noob", "stop talking", "openQA is unavailable, due to LOL"}
	};
	
	public HelloWorldRetriever(Map<String, Object> params) {
		super(params);
	}
	
	@Override
	public boolean canProcess(IParam param) {
		// check if the argument have the required attribute
		return param.contains(HelloWorldParameters.Property.MATRIX_LINE, HelloWorldParameter.class);
	}

	@Override
	public List<? extends IResult> process(IParam param,
			ServiceProvider services, IContext context) throws Exception {
		HelloWorldParameter helloWorldParameter = param.getProperty(HelloWorldParameters.Property.MATRIX_LINE, HelloWorldParameter.class);
		int response = helloWorldParameter.getMatrixLine();
		
		int r = (int) Math.floor(Math.random() *  answers[response].length);
		
		// print the answer
		String answer = answers[response][r];
		
		List<IResult> results = new ArrayList<>();
		Result result = new Result();
		result.setProperty(Properties.Literal.TEXT, answer);
		results.add(result);
		
		return results; // since we already consume the parameter, return null
	}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package org.aksw.openqa.examples.example3;

import org.aksw.openqa.component.object.Param;
import org.aksw.openqa.examples.HelloWorldParameters;

public class HelloWorldParameter extends Param {
	
	public void setMatrixLine(Integer matrixLine) {
		setProperty(HelloWorldParameters.Property.MATRIX_LINE, matrixLine);
	}
	
	public Integer getMatrixLine() {
		return getProperty(HelloWorldParameters.Property.MATRIX_LINE, Integer.class);
	}
}
1
org.aksw.openqa.examples.example3.HelloWorldInterpreterFactory
1
org.aksw.openqa.examples.example3.HelloWorldRetrieverFactory
1
2
3
4
5
6
version=example3
label=HelloWorldInterpreter
author=Edgard Marx
contact=http://openqa.aksw.org
description=Hello world interpreter of openQA framework.
license=Apache License 2.0
1
2
3
4
5
6
version=example3
label=HelloWorldRetriever
author=Edgard Marx
contact=http://openqa.aksw.org
description=Hello world retriever of openQA framework.
license=Apache License 2.0