001    // This file is part of the Attempto Java Packages.
002    // Copyright 2008-2009, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch).
003    //
004    // The Attempto Java Packages is free software: you can redistribute it and/or modify it under the
005    // terms of the GNU Lesser General Public License as published by the Free Software Foundation,
006    // either version 3 of the License, or (at your option) any later version.
007    //
008    // The Attempto Java Packages is distributed in the hope that it will be useful, but WITHOUT ANY
009    // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
010    // PURPOSE. See the GNU Lesser General Public License for more details.
011    //
012    // You should have received a copy of the GNU Lesser General Public License along with the Attempto
013    // Java Packages. If not, see http://www.gnu.org/licenses/.
014    
015    package ch.uzh.ifi.attempto.acewiki.gui.editor;
016    
017    import java.util.ArrayList;
018    import java.util.List;
019    
020    import nextapp.echo2.app.event.ActionEvent;
021    import nextapp.echo2.app.event.ActionListener;
022    import ch.uzh.ifi.attempto.acewiki.Task;
023    import ch.uzh.ifi.attempto.acewiki.Wiki;
024    import ch.uzh.ifi.attempto.acewiki.core.ontology.OntologyElement;
025    import ch.uzh.ifi.attempto.acewiki.core.ontology.Sentence;
026    import ch.uzh.ifi.attempto.acewiki.core.ontology.Statement;
027    import ch.uzh.ifi.attempto.acewiki.gui.page.ArticlePage;
028    import ch.uzh.ifi.attempto.echocomp.MessageWindow;
029    import ch.uzh.ifi.attempto.preditor.PreditorWindow;
030    import ch.uzh.ifi.attempto.preditor.text.TextContainer;
031    import ch.uzh.ifi.attempto.preditor.text.TextElement;
032    
033    /**
034     * This class manages the predictive editor. It creates the editor window and handles its
035     * responses.
036     * 
037     * @author Tobias Kuhn
038     */
039    public class SentenceEditorHandler implements ActionListener {
040            
041            private static final long serialVersionUID = -2083910385095284075L;
042            
043            private PreditorWindow editorWindow;
044            private MessageWindow messageWindow;
045            private ArticlePage page;
046            private Wiki wiki;
047            private boolean edit;
048            private Statement statement;
049            private List<Sentence> newSentences = new ArrayList<Sentence>();
050            private int checked = 0;
051            
052            private SentenceEditorHandler(Statement statement, ArticlePage page, boolean edit) {
053                    this.page = page;
054                    this.wiki = page.getWiki();
055                    this.edit = edit;
056                    this.statement = statement;
057                    AceWikiMenuCreator menuCreator = new AceWikiMenuCreator(wiki, page.getOntologyElement(), this);
058                    editorWindow = new PreditorWindow("Sentence Editor", wiki.getGrammar(), menuCreator);
059                    editorWindow.setLogger(wiki.getLogger());
060                    editorWindow.addActionListener(this);
061                    editorWindow.setContextChecker(Sentence.contextChecker);
062                    
063                    if (edit) {
064                            String t = ((Sentence) statement).getPrettyText();
065                            // remove the last element (i.e. the period '.' or question mark '?'):
066                            editorWindow.addText(t.substring(0, t.length()-1) + " ");
067                    }
068            }
069            
070            /**
071             * Generates a new preditive editor (short "preditor") window to create a new sentence.
072             * 
073             * @param followingStatement The statement in front of which the new sentences should be added,
074             *   or null if the sentences should be added to the end of the article.
075             * @param page The host page into which the sentence should be added.
076             * @return A new preditor window.
077             */
078            public static PreditorWindow generatePreditorAddWindow(Statement followingStatement, ArticlePage page) {
079                    SentenceEditorHandler h = new SentenceEditorHandler(followingStatement, page, false);
080                    return h.getPreditorWindow();
081            }
082            
083            /**
084             * Generates a new preditive editor (short "preditor") window to create a new sentence.
085             * 
086             * @param sentence The sentence that should be edited.
087             * @param page The host page which contains the sentence to be edited.
088             * @return A new preditor window.
089             */
090            public static PreditorWindow generatePreditorEditWindow(Sentence sentence, ArticlePage page) {
091                    SentenceEditorHandler h = new SentenceEditorHandler(sentence, page, true);
092                    return h.getPreditorWindow();
093            }
094            
095            private PreditorWindow getPreditorWindow() {
096                    return editorWindow;
097            }
098    
099            public void actionPerformed(ActionEvent e) {
100                    if (e.getSource() == editorWindow && e.getActionCommand().equals("OK")) {
101                            TextContainer textContainer = editorWindow.getTextContainer();
102                            
103                            ArrayList<TextElement> finalElements = editorWindow.getPossibleNextTokens(".", "?");
104                            if (!finalElements.isEmpty()) textContainer.addElement(finalElements.get(0));
105                            
106                            ArrayList<TextElement> l = textContainer.getTextElements();
107                            if (l.isEmpty() || l.get(l.size() - 1).getText().matches("[.?]")) {
108                                    newSentences = Sentence.generateSentences(textContainer, page.getOntologyElement());
109                                    checkSentence();
110                            } else {
111                                    wiki.log("edit", "error: unfinished sentences");
112                                    MessageWindow mw = new MessageWindow("Error", "There are unfinished sentences.", editorWindow, "OK");
113                                    page.getWiki().showWindow(mw);
114                            }
115                    } else if (e.getSource() == editorWindow && e.getActionCommand().equals("Cancel")) {
116                            editorWindow.setVisible(false);
117                            editorWindow.dispose();
118                    } else if (e.getSource() == messageWindow && e.getActionCommand().equals("a ...")) {
119                            checked++;
120                            checkSentence();
121                    } else if (e.getSource() == messageWindow && e.getActionCommand().equals("every ...")) {
122                            String text = newSentences.get(checked).getText();
123                            text = text.replaceFirst("^(A|a)n? ", "Every ");
124                            newSentences.remove(checked);
125                            newSentences.add(checked, new Sentence(text, page.getOntologyElement()));
126                            checked++;
127                            checkSentence();
128                    } else if (e.getSource() == messageWindow && e.getActionCommand().equals("Close")) {
129                            checked = 0;
130                    } else if (e.getSource() instanceof TextElement) {
131                            editorWindow.addTextElement((TextElement) e.getSource());
132                    }
133            }
134            
135            private void checkSentence() {
136                    if (checked >= newSentences.size()) {
137                            assertSentences();
138                    } else {
139                            List<TextElement> t = newSentences.get(checked).getTextElements();
140                            String t0 = t.get(0).getText();
141                            String t1 = t.get(1).getText();
142                            String l = t.get(t.size()-1).getText();
143                            if (t0.matches("(A|a)n?") && !t1.matches(".* of") && l.equals(".")) {
144                                    String s = t.get(1).getText();
145                                    messageWindow = new MessageWindow(
146                                                    "Warning",
147                                                    "Your sentence \"a " + s + " ...\" is interpreted as \"there is a " + s + " that ...\". " +
148                                                            "Do you want to say \"every " + s + " ...\"?",
149                                                    editorWindow,
150                                                    this,
151                                                    "a ...", "every ..."
152                                            );
153                                    wiki.showWindow(messageWindow);
154                            } else {
155                                    checked++;
156                                    checkSentence();
157                            }
158                    }
159            }
160            
161            private void assertSentences() {
162                    final TextContainer textContainer = editorWindow.getTextContainer();
163                    final OntologyElement el = page.getOntologyElement();
164                    
165                    Task task = new Task() {
166                            
167                            int success;
168                            
169                            public void run() {
170                                    if (edit) {
171                                            wiki.log("edit", "sentence updated: " + textContainer.getText());
172                                            success = el.edit(statement, new ArrayList<Statement>(newSentences));
173                                    } else {
174                                            wiki.log("edit", "sentence created: " + textContainer.getText());
175                                            success = el.add(statement, new ArrayList<Statement>(newSentences));
176                                    }
177                            }
178                            
179                            public void updateGUI() {
180                                    page.update();
181                                    if (success == 1) {
182                                            wiki.showWindow(
183                                                    new MessageWindow(
184                                                            "Conflict",
185                                                            "A sentence is in conflict with the current knowledge. For that reason, " +
186                                                                    "it cannot be added to the knowledge base.",
187                                                            "OK"
188                                                    )
189                                            );
190                                    } else if (success == 2) {
191                                            wiki.showWindow(
192                                                    new MessageWindow(
193                                                            "Error",
194                                                            "A sentence could not be added to the knowledge base because the knowledge " +
195                                                                    "base got too complex.",
196                                                            "OK"
197                                                    )
198                                            );
199                                    }
200                                    if (page != null) {
201                                            page.update();
202                                            page.getWiki().update();
203                                    }
204                            }
205                            
206                    };
207                    
208                    if (edit) {
209                            wiki.enqueueAsyncTask("Updating", "The knowledge base is being updated...", task);
210                    } else {
211                            wiki.enqueueAsyncTask("Updating", "The sentence is being added to the knowledge base...", task);
212                    }
213                    
214                    editorWindow.setVisible(false);
215            }
216    
217    }