I tried first to put all Classe(key) and SuperClasses(value :ArrayList, direct superClasses) of the ontology (I want that the last element of the ontology be the root of my treeView) in a HashMap (hm).
However I don't know how to put properly this hashmap in a TreeView.
A recursive tree would suit much better but I don't know how to do that. (I have a method who convert a recursive data structure in a treeView)
Would anyone be able to give me some clues for my problem?
Thanks !
method who return the hashmap :
public HashMap<String, ArrayList<String>> getClassesHashMap() {
HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();
OWLReasonerFactory reasonerFactory = new StructuralReasonerFactory();
OWLReasoner reasonerFactory3 = reasonerFactory.createReasoner(ontology);
OWLDataFactory fac3 = ontology.getOWLOntologyManager().getOWLDataFactory();
for (String s : getClassesName()) {
IRI docIRI = IRI.create(ontology.getOntologyID().getOntologyIRI().get() + "#" + s);
OWLClass pizza = fac3.getOWLClass(docIRI);
NodeSet<OWLClass> subClses = reasonerFactory3.getSuperClasses(pizza, true);
Set<OWLClass> clses = subClses.getFlattened();
System.out.println("Subclasses of " + s + " : ");
//instanciate the hashmap
for (OWLClass cls1 : clses) {
//cls1.getIRI().getShortForm() is the name of an ontology classes in String
//all the classe is a key, and their superclasses is the value
if (!cls1.getIRI().getShortForm().equals("Thing")) {
if (!hm.containsKey(s)) {
hm.put(s, new ArrayList<String>());
}
hm.get(s).add(cls1.getIRI().getShortForm());
System.out.println(" " + cls1.getIRI().getShortForm());
}
System.out.println();
}
}
// Tree<String> res = new Tree<String>("");
return hm;
}
Method who instanciate the TreeView
private void initTreeView() throws OWLException {
// TreeItem<String> root = new TreeItem<String>("Private_Policy");
tree.setFixedCellSize(25);
//Privacy Policy is the Ontology classe I Use
TreeItem<String> root = new TreeItem<String>("PrivacyPolicy");
root.setExpanded(true);
OntologieDAO ont = new OntologieDAO("WotPriv.owl");
//hashmap of the ontology
HashMap<String, ArrayList<String>> hm = ont.getClassesHashMap();
TreeItem<String> children = new TreeItem<String>("");
System.out.println(hm);
int i = 0;
//work only for my ontology
for (String s : hm.get(root.getValue())) {
TreeItem<String> tI = new TreeItem<String>(s);
root.getChildren().add(tI);
if (hm.containsKey(s)) {
for (String s1 : hm.get(s)) {
TreeItem<String> n = new TreeItem<String>(s1);
TreeItem<String> tI1=root.getChildren().get(root.getChildren().indexOf(tI));
tI1.getChildren().add(n);
if (hm.containsKey(s1)) {
for (String s2 : hm.get(s1)) {
tI1.getChildren().get(tI1.getChildren().indexOf(n)).getChildren().add(new TreeItem<String>(s2));
}}
}
}
}
tree.setRoot(root);
tree.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
System.out.println(ont.getClassesName());
}
A recursive data structure and a method to convert it in treeview :
import java.util.HashSet;
import java.util.Set;
public class MyType<N> {
private Set<MyType<N>> children = new HashSet<>();
private N Value;
public MyType(N value) {
super();
Value = value;
}
public Set<MyType<N>> getChildren() {
return children;
}
public void setChildren(Set<MyType<N>> children) {
this.children = children;
}
public N getValue() {
return Value;
}
public void setValue(N value) {
Value = value;
}
}
private TreeItem<MyType<String>> buildSubtree(MyType<String> root) {
TreeItem<MyType<String>> result = new TreeItem<>(root);
if (root.getChildren() != null) {
for (MyType<String> child : root.getChildren()) {
result.getChildren().add(buildSubtree(child));
}
}
return result;
}
(Image) Result I want to have (I already have it but my code is really dirty and would'nt work with other ontology)
Related
So I have a Map<String, ArrayList> parentToChild and want to create basically a "Family Tree" or nested hierarchy. Below is an example of the map but there could be more children at each level e.g. (Claire could have Matt and Bruce as children):
David -> [Claire]
Claire -> [Matt]
Matt -> [Sean, Terry]
I know the root of the tree should be David for the above example and it will only have one root.
Example output
{
"David": {
"Claire": {
"Matt": {
"Sean": {},
"Terry": {}
}
}
}
}
I've tried few things but genuinely stumped.
EDIT: Code tried so far
public Set<Tree> transform(Map<String, ArrayList<String>> input) {
Set<String> roots = new HashSet<String>(input.keySet());
Map<String, Tree> map = new HashMap<String, Tree>();
for (Map.Entry<String, ArrayList<String>> entry : input.entrySet()) {
String key = entry.getKey();
List<String> childKeys = entry.getValue();
Tree tree = map.get(key);
if (tree == null) {
tree = new Tree(key);
map.put(key, tree);
}
for (String childKey : childKeys) {
roots.remove(childKey);
Tree child = map.get(childKey);
if (child == null) {
child = new Tree(childKey);
map.put(childKey, child);
}
tree.addChild(child);
}
}
Set<Tree> res = new HashSet<Tree>(roots.size());
for (String key : roots) {
res.add(map.get(key));
}
return res;
}
Tree class:
public class Tree {
private String key;
private Tree child;
public Tree(String key){
this.key = key;
}
public void addChild(Tree child){
this.child = child;
}
}
The issue is when I use this code the output (What is in the set after debugging/printing) I get is
David:
Claire:
Matt:
Terry:
You could use a Map<String,Object>:
private static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
.create();
public static void main(String[] args) {
Map<String, List<String>> input = new HashMap<>();
input.put("David", Arrays.asList("Claire"));
input.put("Claire", Arrays.asList("Matt"));
input.put("Matt", Arrays.asList("Sean", "Terry"));
Map<String,Object> result = new HashMap<>();
convert(input, "David", result);
GSON.toJson(result, System.out);
}
private static void convert(Map<String, List<String>> input, String root,
Map<String,Object> result) {
if (!result.containsKey(root)) {
Map<String,Object> rootObj = new HashMap<>();
result.put(root, rootObj);
List<String> children = input.get(root);
if (children != null) {
for (String child: children) {
convert(input, child, rootObj);
}
}
}
}
Output:
{
"David": {
"Claire": {
"Matt": {
"Terry": {},
"Sean": {}
}
}
}
}
In the Java world you have access to Saxon 9.8 or later HE where XPath 3.1 or XQuery 3.1 or XSLT 3.0 all have support for representing your initial map as an XdmMap and processing them, for instance with XQuery:
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method 'json';
declare option output:indent 'yes';
declare variable $map as map(xs:string, array(xs:string)) external := map {
'David' : [ 'Claire' ],
'Claire' : [ 'Matt' ],
'Matt' : [ 'Sean', 'Terry' ]
};
declare variable $root as xs:string external := 'David';
declare function local:create-tree($map as map(xs:string, array(xs:string)), $children as xs:string*) as map(*) {
map:merge($children ! map { . : local:create-tree($map, $map(.)) })
};
local:create-tree($map, $root)
https://xqueryfiddle.liberty-development.net/3Nzd8bV
A simple Java example to run this with Saxon 10 HE (its API documentation is at http://saxonica.com/html/documentation/using-xquery/api-query/s9api-query.html), passing a Java Map to the XQuery (inserted inline as a string but could of course be loaded from a file instead) is:
import java.util.HashMap;
import java.util.Map;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XQueryCompiler;
import net.sf.saxon.s9api.XQueryEvaluator;
import net.sf.saxon.s9api.XQueryExecutable;
import net.sf.saxon.s9api.XdmMap;
public class SaxonJavaMapToNestedJSONObject {
public static void main(String[] args) throws SaxonApiException {
Map<String, String[]> map = new HashMap<>();
map.put("David", new String[] { "Claire" });
map.put("Claire", new String[] { "Matt" });
map.put("Matt", new String[] { "Sean", "Terry" });
Processor processor = new Processor(true);
XQueryCompiler compiler = processor.newXQueryCompiler();
XQueryExecutable executable = compiler.compile("declare namespace map = \"http://www.w3.org/2005/xpath-functions/map\";\n" +
"\n" +
"declare namespace output = \"http://www.w3.org/2010/xslt-xquery-serialization\";\n" +
"\n" +
"declare option output:method 'json';\n" +
"declare option output:indent 'yes';\n" +
"\n" +
"declare variable $map as map(xs:string, array(xs:string)) external;\n" +
"\n" +
"declare variable $root as xs:string external := 'David';\n" +
"\n" +
"declare function local:create-tree($map as map(xs:string, array(xs:string)), $children as xs:string*) as map(*) {\n" +
" map:merge($children ! map { . : local:create-tree($map, $map(.)) })\n" +
"};\n" +
"\n" +
"local:create-tree($map, $root)");
XQueryEvaluator evaluator = executable.load();
evaluator.setExternalVariable(new QName("map"), XdmMap.makeMap(map));
evaluator.run(processor.newSerializer(System.out));
}
}
Of course you could set the root variable as well from Java: evaluator.setExternalVariable(new QName("root"), new XdmAtomicValue("David"));
I have a properties file like this.
property[0].name=A
property[0].value=1
property[1].name=B
property[1].value=2
property[2].name=C
property[2].value=3
How to read this file as a list of objects of a class {name, value} in plain java program using ResourceBundle or Properties?
Here is the class.
public class XYZ {
private String name;
private String value;
// Getters & Setters
}
I need to get like this.
ArrayList<XYZ> propertiesList = SomeUtility.getProperties("property", XYZ.class);
Utility class might be like this.
public class SomeUtility {
public static ArrayList getProperties(String key, Class cls) {
//logic
}
}
I might not understand exactly what you want so feel free to correct me and give me more constraints to work with but here is a simple way to read a Properties file located somewhere in your project:
private static void readPropertiesFile(String path) throws IOException {
java.util.Map<String, String> map = new java.util.LinkedHashMap<>();
Properties properties = new Properties();
InputStream inputStream = new FileInputStream(path);
properties.load(inputStream);
for (String name : properties.stringPropertyNames()) {
map.put(name, properties.getProperty(name));
}
for (java.util.Map.Entry<String, String> entry : map.entrySet()) {
System.out.printf("Property Key: %s, Property Value: %s%n", entry.getKey(), entry.getValue());
}
}
Output
Property Key: property[0].name, Property Value: A
Property Key: property[1].name, Property Value: B
Property Key: property[0].value, Property Value: 1
Property Key: property[1].value, Property Value: 2
Property Key: property[2].name, Property Value: C
Property Key: property[2].value, Property Value: 3
This is the solution I wrote, but it involves Reflect and Gson. Is there any better way to do this? Anything already available which is fine tuned like Apache's.
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.lang.reflect.Field;
import java.util.*;
public class ListResourceBundle {
public static final Gson gson = new Gson();
private final ResourceBundle bundle;
public ListResourceBundle(ResourceBundle bundle) {
this.bundle = bundle;
}
public List<?> getProperties(String key, Class<?> cls) {
final int maxArraySize = getMaxArraySize(key, getMatchingKeys(key));
final List<String> fields = getFields(cls);
final List<Object> result = new ArrayList<>();
for (int i = 0; i < maxArraySize; i++) {
JsonObject jsonObject = new JsonObject();
for (String field : fields) {
jsonObject.addProperty(field, getStringOrNull(key + "[" + i + "]." + field));
}
result.add(gson.fromJson(jsonObject, cls));
}
System.out.println("result.toString() = " + result.toString());
return result;
}
public List<String> getMatchingKeys(String key) {
Enumeration<String> keys = bundle.getKeys();
List<String> matchingKeys = new ArrayList<>();
while(keys.hasMoreElements()) {
String k = keys.nextElement();
if(k.startsWith(key)) {
matchingKeys.add(k);
}
}
Collections.sort(matchingKeys);
return matchingKeys;
}
public int getMaxArraySize(String key, List<String> matchingKeys) {
int maxArraySize = 0;
for (int i = 0; ; i++) {
boolean indexAvailable = false;
for (String matchingKey : matchingKeys) {
if(matchingKey.startsWith(key + "[" + i + "]")) {
indexAvailable = true;
break;
}
}
if(indexAvailable) {
maxArraySize++;
} else {
break;
}
}
return maxArraySize;
}
public String getStringOrNull(String key) {
try {
return bundle.getString(key);
} catch (MissingResourceException e) {
return null;
}
}
public List<String> getFields(Class<?> cls) {
final List<String> fields = new ArrayList<>();
for (Field field : cls.getDeclaredFields()) {
fields.add(field.getName());
}
return fields;
}
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("com.example.application.resources.Resource");
ListResourceBundle applicationResourceBundle = new ListResourceBundle(bundle);
applicationResourceBundle.getProperties("property", ReportParam.class);
}
}
Resource:
property[0].name=A
property[0].value=1
property[1].name=B
property[1].value=2
property[2].name=C
property[2].value=3
Output:
result.toString() = [
ReportParam{name='A', value='1'},
ReportParam{name='B', value='2'},
ReportParam{name='C', value='3'}]
Process finished with exit code 0
I know it's bit late of an answer, but if I understand your problem statement correctly, you can use :
#ConfigurationProperties
to get your job done.
Here is my spring-boot example with a YAML file for the sake of convenience (same can be achieved through properties file as well).
application.yaml:
xyz:
xyzprops :
-
name: cbc
value: 441
-
name: obc
value: 443
XYZ class:
#Component
#ConfigurationProperties(prefix = "xyz")
public class XYZ{
private List<XYZProps> xyzprops;
public List<XYZProps> getXyzprops() {
return xyzprops;
}
public void setXyzprops(List<XYZProps> xyzprops) {
this.xyzprops = xyzprops;
}
public class XYZProps{
String name;
String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
And then #Autowire XYZ where you want to use it.
I would use JSON:
in your file:
property=[{"name":"A","value":"1"},{"name":"B","value":"2"},{"name":"C","value":"3"}]
and then deserialize it using com.google.gson.gson (or any other) library:
ArrayList<XYZ> propertiesList;
propertiesList = new gsonbuilder().create().fromjson(property, propertiesList.class);
NOTE: I haven't tested this code, and i'm not very familiar with java so i am sure there is a better,cleaner way to implement this.
I am trying to acheive JSON to JSON conversion in java based on the specification given on runtime.
Example : if at runtime source : com.gsdetails.gname,target : com.track.trackName (i.e source field should be mapped to target field in generated JSON)
My approach was to create N-array tree for the specification part and do breadth first travesal (get queue with it to craeate structure for resulting json)
I am using Jackson api to create tree from input JSON and traversing both queue(bfs) and input tree to create resulting json.
Unable to get expected output
PS : I thought of using JOLT api but it will not serve my purpose
Tree (for specification)
public class TrieBuilder {
public static void main(String[] args) throws Exception {
createSpec();
}
public static Trie createSpec() throws Exception {
BufferedReader reader = new BufferedReader(
new FileReader(""));
String currentLine = reader.readLine();
Trie trie = new Trie();
while (currentLine != null) {
String[] lines = currentLine.split(",");
String sourceLine = lines[0];
String targetLine = lines[1];
String sourcePath = sourceLine.split("=")[1];
String targetPath = targetLine.split("=")[1];
trie.insertWord(sourcePath.trim(), targetPath.trim());
currentLine = reader.readLine();
}
return trie;
}
}
class TrieNode {
String source;// consider this as content/reference point of a tree
String target;
boolean isEnd;
int count;
List childList;
boolean isRoot;
/* Constructor */
public TrieNode(String source, String target) {
childList = new ArrayList<TrieNode>();
isEnd = false;
count = 0;
this.source = source;
this.target = target;
}
public TrieNode subNodeWord(String word) {
if (childList != null) {
for (TrieNode eachChild : childList)
if (eachChild.source.equals(word))
return eachChild;
}
return null;
}
}
class Trie {
public TrieNode root;
/* Constructor */
public Trie() {
root = new TrieNode("", "");
}
public void insertWord(String sourceWords, String targetWords) {
if (searchWord(sourceWords) == true)
return;
TrieNode current = root;
String[] sourceArray = sourceWords.split(":");
String[] targetArray = targetWords.split(":");
for (int i = 0; i < sourceArray.length; i++) {
TrieNode child = current.subNodeWord(sourceArray[i]);
if (child != null) {
current = child;
} else {
current.childList.add(new TrieNode(sourceArray[i],
targetArray[i]));
current = current.subNodeWord(sourceArray[i]);
}
current.count++;
}
current.isEnd = true;
}
public boolean searchWord(String words) {
TrieNode current = root;
for (String word : words.split(":")) {
if (current.subNodeWord(word) == null) {
return false;
} else {
current = current.subNodeWord(word);
}
}
if (current.isEnd == true)
return true;
return false;
}
public Queue<TrieNode> bfsTraversal(TrieNode node) {
// TODO need to add logic for bfs/dfs for traversing the trie
Queue<TrieNode> queue = new LinkedList<>();
Queue<TrieNode> tempQueue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TrieNode tempNode = queue.poll();
tempQueue.add(tempNode);
int counter = tempNode.childList.size(), i = 0;
if (tempNode == null)
break;
if (!tempNode.source.isEmpty())
System.out.println("Source :" + tempNode.source
+ " Target : " + tempNode.target);
while (i < counter) {
queue.add(tempNode.childList.get(i++));
}
}
tempQueue.poll();
return tempQueue;
}
Source to target mapping file :
source = com:track:trackDetails:fname, target = gsUser:gsProp:gsDetails:gsFirstName
source = com:track:trackDetails:lname, target = gsUser:gsProp:gsDetails:gsLastName
helper class (Actual transform):
public class JsonHelperClass{
// private Files file = null;// create a tempfile
private JsonNodeFactory factory;
private JsonFactory jsonFactory;
private ObjectMapper mapper;
private JsonNode jsonRoot;
private Queue<TrieNode> queue;
// private JsonParser jsonParser =
public JsonHelperClass() throws JsonProcessingException, IOException {
this.factory = JsonNodeFactory.instance;
this.jsonFactory = new JsonFactory();
this.mapper = new ObjectMapper();
this.jsonRoot = mapper.readTree(new File("json with data"));
}
public static void main(String[] args) throws Exception, Exception {
JsonHelperClass helperClass = new JsonHelperClass();
helperClass.jsonCreator();
ObjectNode objectNode = null;
ObjectNode result = helperClass.createJsonRecursively(objectNode);
System.out.println(result.toString());
}
public void jsonCreator() throws Exception {
Trie trie = TrieBuilder.createSpec();
queue = trie.bfsTraversal(trie.root);
}
public ObjectNode createJsonRecursively(ObjectNode outputJson) throws Exception {
TrieNode nodeOfQueue = queue.poll();
if(outputJson == null){
// create a root of the JSON
outputJson = factory.objectNode();
outputJson.put(nodeOfQueue.target, createJsonRecursively(outputJson));
}else if (jsonRoot.get(nodeOfQueue.source).isObject()){
// create an object to conatin other values/object
ObjectNode objectNode = factory.objectNode();
objectNode.put(nodeOfQueue.target,createJsonRecursively(outputJson));
outputJson.putAll(objectNode);
}else if(jsonRoot.get(nodeOfQueue.source).isArray()){
// create an array node and call for to create value it contains
ArrayNode arrayNode = factory.arrayNode();
int size = jsonRoot.get(nodeOfQueue.source).size();
for(int index = 0 ; index < size ; index++){
arrayNode.add(jsonRoot.get(nodeOfQueue.source).get(index));
}
outputJson.put(nodeOfQueue.target,arrayNode);
}else if(nodeOfQueue.isEnd){
// create leaf node
outputJson.put(nodeOfQueue.target, jsonRoot.get(nodeOfQueue.source));
return outputJson;
}
return outputJson;
}
I have MaterailInfo and StyleInfo, I want to set styleDescription based on StyleNumber matching with materialNumber. I am using 2 for loops, is there any alternative solution?
MaterailInfo:
class MaterailInfo {
private String materialNumber;
private String materialDescription;
public MaterailInfo(String materialNumber, String materialDescription) {
this.materialNumber = materialNumber;
this.materialDescription = materialDescription;
}
// getter setter methods
}
StyleInfo:
class StyleInfo {
private String StyleNumber;
private String styleDescription;
public StyleInfo(String styleNumber, String styleDescription) {
StyleNumber = styleNumber;
this.styleDescription = styleDescription;
}
// getter setter toString methods
}
TEst12:
public class TEst12 {
public static void main(String[] args) {
List<MaterailInfo> mList = new ArrayList<MaterailInfo>();
mList.add(new MaterailInfo("a", "a-desc"));
mList.add(new MaterailInfo("b", "b-desc"));
mList.add(new MaterailInfo("c", "c-desc"));
List<StyleInfo> sList = new ArrayList<StyleInfo>();
sList.add(new StyleInfo("a", ""));
sList.add(new StyleInfo("b", ""));
sList.add(new StyleInfo("c", ""));
for (MaterailInfo m : mList) {
for (StyleInfo s : sList) {
if (s.getStyleNumber().equals(m.getMaterialNumber())) {
s.setStyleDescription(m.getMaterialDescription());
}
}
}
System.out.println(sList);
}
}
If you use a Map instead of a List to store your data, you can get away with doing only a single loop:
Map<String, String> mMap = new HashMap<String, String>();
mMap.put("a", "a-desc");
mMap.put("b", "b-desc");
mMap.put("c", "c-desc");
Map<String, String> sMap = new HashMap<String, String>();
sMap.put("a", "");
sMap.put("b", "");
sMap.put("c", "");
for (Map.Entry<String, String> entry : mMap.entrySet()) {
sMap.put(entry.getKey(), mMap.get(entry.getKey());
}
This code will leave the style description empty if the style number does not match any known material number.
If your numbers can't have duplicates, using a HashMap instead of classes can be a bit faster.
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
public class Demo {
public static void main(String[] args) {
HashMap<String, String> mList = new HashMap();
HashMap<String, String> sList = new HashMap();
mList.put("a", "a-desc");
mList.put("b", "b-desc");
mList.put("c", "c-desc");
sList.put("a", "");
sList.put("b", "");
sList.put("c", "");
Iterator entries = sList.entrySet().iterator();
while (entries.hasNext()) {
Entry entry = (Entry) entries.next();
if (mList.containsKey(entry.getKey())) {
sList.put((String) entry.getKey(), mList.get(entry.getKey()));
}
}
for (Map.Entry<String, String> entry : sList.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
}
You can do this using one for loop like this
for (int i = 0; i < mList.size(); i++) {
sList.get(i).setStyleDescription(mList.get(i).getMaterialDescription());
}
Note: i am assuming you have balanced lists in term of size.
I'm new to eclipse development and I'm working on a custom namepatternfilter for Jface tree viewer. I have the below code in my filter which recursively goes through children of a node element.
public boolean isChildMatch(final Object element) {
boolean value = false;
// Object[] children = this.contentProvider.getChildren(element);
Object[] items = null;
if (((HashMap<Object, String>) getTreeMap().get(element)) == null) {
final Object[] children = this.contentProvider.getChildren(element);
items = children;
new Thread(new Runnable() {
#Override
public void run() {
final HashMap<Object, String> childrenMap = new HashMap<Object, String>();
for (Object object : children) {
childrenMap.put(object, null);
}
NamePatternFilter.this.getTreeMap().put(element, childrenMap);
}
}).start();
}
else {
items = ((HashMap<Object, String>) getTreeMap().get(element)).keySet().toArray();
}
for (Object child : items) {
if (isElementMatch(child)) {
value = true;
break;
}
else if (isChildMatch(child)) {
this.visibleElements.add(child);
value = true;
break;
}
}
return value;
}
When i run the code, I'm getting stackoverflow exception
org.eclipse.swt.SWTException: Failed to execute runnable (java.lang.StackOverflowError)
at org.eclipse.swt.SWT.error(SWT.java:4441)
at org.eclipse.swt.SWT.error(SWT.java:4356)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:139)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4147)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3764)
What am I missing here?