1

I’m developing a companion bot for dementia suffers able to record, store and integrate memories into conversation. The bot calls an xml. file for conversations which can detect contexts passing an argument via baseContext.xml to call a topic.class and dynamically reload new xml data parser and bot while Main.class continues other tasks.

However, I can’t decide if trying to reload the parser/bot into JVM is feasible or whether pausing the class threads and calling a new class/es would be the best solution, or another solution is available. Ideally I’d like to pass the new xml data into the JVM while the other classes persist.

Any help much appreciated.

Main Class (calls the bot, camera, scheduler, text history etc)

public class Main extends javax.swing.JFrame {

private static Bot bot;    
public BlockingQueue<String> queue;

public Main() {
    initComponents();

    //get the parser going
    DataParser dp = new DataParser();

    //make new bot with level 0 as default and given data parser
    bot = new Bot("0", dp);

    //dispaly the default message
    txtHistory.setText("Bot: " + bot.getMessage()); 
}
public Main(BlockingQueue<String>queue) {
            this.queue = queue;
  }
     // display bot response in the text area
     private static final String VOICENAME="kevin16";
     private static void addBotText(String message) {
    txtHistory.setText(txtHistory.getText() + "\nBot: " + message);
    //turn the bot response to sound
    Voice voice;
        VoiceManager vm= VoiceManager.getInstance();
        voice=vm.getVoice(VOICENAME);

        voice.allocate();

        try{
            voice.speak(bot.getMessage());
        }catch(Exception e){
    }
    voice.deallocate();
}
public static void listen (String speech) {        

    txtHistory.setText(txtHistory.getText() + "\nYou: " + speech + "\n");

    //send the input to the bot and get bot response

The Data parser class deals with the xml loading into DOM

    package bot;

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;

    public class DataParser {
        private Document dom;
        private HashMap<String, State> states = new HashMap<String, State>();
        private ArrayList<String> invalidMessages = new ArrayList();
        private int invalidMessageIndex = 0;
        public  int stateCounter = 1000; 
        public String fileSource;
        // default constructor
        public DataParser() {
            // Load the XML file and parse it
            DocumentBuilderFactory dbf =                                 DocumentBuilderFactory.newInstance();

            try {

        //get the filepath of source
        String fileSource = Context.getSource();

        DocumentBuilder db = dbf.newDocumentBuilder();

        //parse using builder to get DOM representation of the XML file
        dom = db.parse(fileSource);

        // Load configuration and states from the XML file
        loadConfiguration();
        loadStates();
    } catch (ParserConfigurationException pce) {
        pce.printStackTrace();
    } catch (SAXException se) {
        se.printStackTrace();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
}

// Load states from XML file
private void loadStates() {

    // get document element object
    Element docEle = dom.getDocumentElement();

    // get all State node names
    NodeList nl = docEle.getElementsByTagName("State");

    // if node is not null and has children
    if (nl != null && nl.getLength() > 0) {

        // loop through all children
        for (int i = 0; i < nl.getLength(); i++) {

            // get state element
            Element el = (Element) nl.item(i);

            // get state id
            String id = el.getAttribute("id");

            // get all state messages
            ArrayList messages = new ArrayList();
            NodeList messagesNodeList =         el.getElementsByTagName("message");

            // if messages node is not null and has children
            if (messagesNodeList != null && messagesNodeList.getLength() > 0) {

                // loop through all children
                for (int j = 0; j < messagesNodeList.getLength(); j++) {

                    // get current message element
                    Element elmsg = (Element) messagesNodeList.item(j);

                    // append message node value to the messages list
                    messages.add(elmsg.getFirstChild().getNodeValue());
                }
            }

            // get keywords in the current state
            ArrayList keywords = getKeywords(el);

            // construct a new State object
            State state = new State(id, messages, keywords);

            stateCounter ++;

            // add the state to the states hashmap
            states.put(id, state);
        }
    }
}

// get state object by id
public State getState(String id) {
    return states.get(id);
}

// create a new state
public void addState(State state){
    states.put(state.getId(), state);
    stateCounter++;
}

// get all keywords in an State tag
public ArrayList getKeywords(Element ele) {

    // construct keywords arraylist
    ArrayList keywords = new ArrayList();

    // get all nodes by keyword tag name
    NodeList nl = ele.getElementsByTagName("keyword");

    // if the tag is not null and has children
    if (nl != null && nl.getLength() > 0) {

        // loop through all the children
        for (int i = 0; i < nl.getLength(); i++) {

            //get the keyword element
            Element el = (Element) nl.item(i);

            // find the keyword target, classname and argument attributes
            String wordTag = el.getFirstChild().getNodeValue();
            String target = el.getAttribute("target");
            String className = el.getAttribute("className");
            String arg = el.getAttribute("arg");
            String variable = el.getAttribute("variable");
            int points = 0;
            try{
                 points = Integer.valueOf(el.getAttribute("points"));
            }catch (Exception e){

            }

            String learn = el.getAttribute("learn");
            // split keyword by comma
            String[] words = wordTag.split(",");

            // loop through all words
            for (String word : words) {

                // trim the word to remove spaces
                word = word.trim();

                // construct a new keyword
                Keyword keyword = new Keyword(word, target, className, arg, variable, points, learn );

                // add the keyword to keywords array list
                keywords.add(keyword);
            }
        }
    }

    // return all the keywords in the given node
    return keywords;
}


// returns one of the invalid messages and move the index to the next message
public String getInvalidAnswer() {

    // get current answer
    String answer = invalidMessages.get(invalidMessageIndex);

    // increase the index, if it is end of messages, reset the index to 0
    invalidMessageIndex++;
    if (invalidMessageIndex >= invalidMessages.size()) {
        invalidMessageIndex = 0;
    }
    return answer;
}

// load cofig tags from data xml file
private void loadConfiguration() {

    // get document element
    Element docEle = dom.getDocumentElement();

    // get all node names for invalid messages
    NodeList node = docEle.getElementsByTagName("InvalidMessages");

    // get all message nodes inside invalid messages node
    NodeList nl = ((Element) node.item(0)).getElementsByTagName("message");

    // if node is not null and has children
    if (nl != null && nl.getLength() > 0) {

        // loop through all children
        for (int i = 0; i < nl.getLength(); i++) {

            // get message node
            Element el = (Element) nl.item(i);

            // get message and add it to invalid messages array
            String message = el.getFirstChild().getNodeValue();
            invalidMessages.add(message);
                }
            }
        }
    }

The bot class manages conversation and calls specialised classes.

    package bot;


    import smallTalk.Morning;
    import smallTalk.Afternoon;
    import smallTalk.Evening;
    import smallTalk.Night;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Map;

    public class Bot {
        // Store all regular expression matches
        private HashMap<String,String> dictionary;

        // Default state to start the bot
        String level = "0";
        DataParser parser;

        // default constructor
        public Bot(String level, DataParser parser) {
            dictionary = new HashMap<String,String>();
            this.level = level;
            this.parser = parser;
        }

        // get current state message
        public String getMessage() {
            State state = parser.getState(level);
            return replaceMatches(state.getMessage()).trim();
        }

        // send user message to the bot and get the response
        public String send(String message) {

            String response = "";
            State state = parser.getState(level);

            // end of the tree
            if (state.getKeywords().isEmpty()) {
                this.level = "0";
            }

            // match the keyword with given message
            Keyword match = parse(message, state.getKeywords());

            // if no keyword is matched, display one of the invalid answers
            if (match == null) {
                response = parser.getInvalidAnswer();
            } else {

                // if match classname is provided, check to get the dynamic response
                if (match.className.length() > 0) {

            // check for Weather dynamic response
            if (match.className.equals("Weather")) {
                Weather weather = new Weather();
                response = weather.getResponse(match.arg);
                this.level = "0";
            }
            // check for News dynamic response
            else if (match.className.equals("News")) {
                News news = new News();
                response = news.getResponse(match.arg);
                this.level = "0";
            }
            else if (match.className.equals("Morning")) {
                Morning morning = new Morning();
                morning.wakeup();
            }
            else if (match.className.equals("Afternoon")) {
                Afternoon afternoon = new Afternoon();
                afternoon.midday();
            }
            else if (match.className.equals("Evening")) {
                Evening evening = new Evening();
                evening.dinner();
            } 
            else if (match.className.equals("Night")) {
                Night night = new Night();
                night.late();
            }
            // check for Topic dynamic response
            else if (match.className.equals("Topic")) {
            Topic topic = new Topic();
            topic.getTopic(match.arg);
            }    
        } else {

            // get the new state and return the new message
            if (response.length() == 0) {

                this.level = match.target;
                state = parser.getState(level);

                // if it is end of the tree
                if (state.getKeywords().isEmpty()) {
                    response = this.getMessage();
                    this.level = "0";

                }
            }
        }
    }
    return response;
}

// parse the given text to find best match in the keywords
private Keyword parse(String text, ArrayList<Keyword> keylist) {

    // set the default match to none
    int bestMatch = -1;
    Keyword match = null;

    // loop through keywords
    for (int i = 0; i < keylist.size(); i++) {

        // get number of matches of the keyword with given text
        int matches = getMatches(text, keylist.get(i));

        // if match is better than best match, replace it
        if (matches > -1 && matches > bestMatch) {
            match = keylist.get(i);
            bestMatch = matches;
        }
    }

    // add best answers regex variable value into the dictionary for future reference
    if (match != null){
        if(match.learn.length() > 0 ){

            // get training data keyword and description
            String subject = dictionary.get(match.learn);
            String result =  match.variableValue;


            // create a new state for new trained data
            ArrayList<String> messages = new ArrayList<String>();
            messages.add(result);
            State myState = new State(String.valueOf(parser.stateCounter),messages,new ArrayList());
            parser.addState(myState);

            // add the new trained keyword
            Keyword keyword = new Keyword(subject, myState.getId(), "", "", "", 1, "" );
            State state = parser.getState("1");
            ArrayList<Keyword> keywords = state.getKeywords();
            keywords.add(keyword);

        }else{
            if (match.variableValue.length() > 0){
                dictionary.put(match.variable, match.variableValue);
            }
        }
    }
    return match;
}

// get number of matches of the given keywords in the given list
private int getMatches(String text, Keyword keyword) {

    // no match by default
    int result = -1;

    // return 0 match when keyword is *
    if(keyword.keyword.equals("*")){
        return keyword.points;
    }

    // if regex is expected
    if(keyword.variable.length() > 0){
        String match = Regex.match(keyword.keyword, text);
        if(match.length() > 0){
            keyword.variableValue = match;
            return keyword.points;
        }
    }

    String[] words = keyword.keyword.split(" ");


    // loop through list of the keywords
    for (String word : words) {

        // if current keyword is in the text, add points
        if (text.toLowerCase().indexOf(word.toLowerCase()) >= 0) {
            result = result + keyword.points + 1;
        } else {
            // return null if one of the keywords does not exists
            return -1;
        }
    }
    return result;
}


// replace given text with variables in the dictionary
public String replaceMatches(String text){

    // replace variables within dictionary in the text
    for (Map.Entry<String, String> entry : dictionary.entrySet()) {
        text = text.replaceAll("\\["+entry.getKey() + "\\]", entry.getValue());
            }

            // remove empty variables tags
            return Regex.clear(text);
        }
    }

The Context class passes the xml file source to data parser.

    package bot;

    public class Context {

        public static String source = "newcontext.xml";

        //method to get value of source called in dataParser

        public static String getSource(){
        return source;
}
        //get the new topic from Topic Class and prepare to reload DataParser/Bot

        public static void newSource(String currentTopic){
        source = currentTopic;
        }
    }

0 Answers0