1

我正在为痴呆症患者开发一个伴侣机器人,能够记录、存储并将记忆整合到对话中。机器人调用 xml。对话文件,可以检测通过 baseContext.xml 传递参数的上下文以调用 topic.class 并动态重新加载新的 xml 数据解析器和机器人,同时 Main.class 继续其他任务。

但是,我无法决定尝试将解析器/机器人重新加载到 JVM 中是否可行,或者暂停类线程并调用新的类/es 是否是最佳解决方案,或者是否有其他解决方案可用。理想情况下,我想将新的 xml 数据传递到 JVM,而其他类仍然存在。

非常感谢任何帮助。

主类(调用机器人、摄像头、调度程序、文本历史记录等)

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

数据解析器类处理 xml 加载到 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);
                }
            }
        }
    }

bot 类管理对话并调用专门的类。

    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);
        }
    }

Context 类将 xml 文件源传递给数据解析器。

    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;
        }
    }
4

0 回答 0