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.addActionListener(this);
060                    
061                    if (edit) {
062                            String t = ((Sentence) statement).getPrettyText();
063                            // remove the last element (i.e. the period '.' or question mark '?'):
064                            editorWindow.addText(t.substring(0, t.length()-1) + " ");
065                    }
066            }
067            
068            /**
069             * Generates a new preditive editor (short "preditor") window to create a new sentence.
070             * 
071             * @param followingStatement The statement in front of which the new sentences should be added,
072             *   or null if the sentences should be added to the end of the article.
073             * @param page The host page into which the sentence should be added.
074             * @return A new preditor window.
075             */
076            public static PreditorWindow generatePreditorAddWindow(Statement followingStatement, ArticlePage page) {
077                    SentenceEditorHandler h = new SentenceEditorHandler(followingStatement, page, false);
078                    return h.getPreditorWindow();
079            }
080            
081            /**
082             * Generates a new preditive editor (short "preditor") window to create a new sentence.
083             * 
084             * @param sentence The sentence that should be edited.
085             * @param page The host page which contains the sentence to be edited.
086             * @return A new preditor window.
087             */
088            public static PreditorWindow generatePreditorEditWindow(Sentence sentence, ArticlePage page) {
089                    SentenceEditorHandler h = new SentenceEditorHandler(sentence, page, true);
090                    return h.getPreditorWindow();
091            }
092            
093            private PreditorWindow getPreditorWindow() {
094                    return editorWindow;
095            }
096    
097            public void actionPerformed(ActionEvent e) {
098                    if (e.getSource() == editorWindow && e.getActionCommand().equals("OK")) {
099                            TextContainer textContainer = editorWindow.getTextContainer();
100                            
101                            ArrayList<TextElement> finalElements = editorWindow.getPossibleNextTokens(".", "?");
102                            if (!finalElements.isEmpty()) textContainer.addElement(finalElements.get(0));
103                            
104                            ArrayList<TextElement> l = textContainer.getTextElements();
105                            if (l.isEmpty() || l.get(l.size() - 1).getText().matches("[.?]")) {
106                                    newSentences = Sentence.generateSentences(textContainer, page.getOntologyElement());
107                                    checkSentence();
108                            } else {
109                                    wiki.log("edit", "error: unfinished sentences");
110                                    MessageWindow mw = new MessageWindow("Error", "There are unfinished sentences.", editorWindow, "OK");
111                                    page.getWiki().showWindow(mw);
112                            }
113                    } else if (e.getSource() == editorWindow && e.getActionCommand().equals("Cancel")) {
114                            editorWindow.setVisible(false);
115                            editorWindow.dispose();
116                    } else if (e.getSource() == messageWindow && e.getActionCommand().equals("a ...")) {
117                            checked++;
118                            checkSentence();
119                    } else if (e.getSource() == messageWindow && e.getActionCommand().equals("every ...")) {
120                            String text = newSentences.get(checked).getText();
121                            text = text.replaceFirst("^(A|a)n? ", "Every ");
122                            newSentences.remove(checked);
123                            newSentences.add(checked, new Sentence(text, page.getOntologyElement()));
124                            checked++;
125                            checkSentence();
126                    } else if (e.getSource() == messageWindow && e.getActionCommand().equals("Close")) {
127                            checked = 0;
128                    } else if (e.getSource() instanceof TextElement) {
129                            editorWindow.addTextElement((TextElement) e.getSource());
130                    }
131            }
132            
133            private void checkSentence() {
134                    if (checked >= newSentences.size()) {
135                            assertSentences();
136                    } else {
137                            List<TextElement> t = newSentences.get(checked).getTextElements();
138                            String t0 = t.get(0).getText();
139                            String t1 = t.get(1).getText();
140                            String l = t.get(t.size()-1).getText();
141                            if (t0.matches("(A|a)n?") && !t1.matches(".* of") && l.equals(".")) {
142                                    String s = t.get(1).getText();
143                                    messageWindow = new MessageWindow(
144                                                    "Warning",
145                                                    "Your sentence \"a " + s + " ...\" is interpreted as \"there is a " + s + " that ...\". " +
146                                                            "Do you want to say \"every " + s + " ...\"?",
147                                                    editorWindow,
148                                                    this,
149                                                    "a ...", "every ..."
150                                            );
151                                    wiki.showWindow(messageWindow);
152                            } else {
153                                    checked++;
154                                    checkSentence();
155                            }
156                    }
157            }
158            
159            private void assertSentences() {
160                    final TextContainer textContainer = editorWindow.getTextContainer();
161                    final OntologyElement el = page.getOntologyElement();
162                    
163                    Task task = new Task() {
164                            
165                            int success;
166                            
167                            public void run() {
168                                    if (edit) {
169                                            wiki.log("edit", "sentence updated: " + textContainer.getText());
170                                            success = el.edit(statement, new ArrayList<Statement>(newSentences));
171                                    } else {
172                                            wiki.log("edit", "sentence created: " + textContainer.getText());
173                                            success = el.add(statement, new ArrayList<Statement>(newSentences));
174                                    }
175                            }
176                            
177                            public void updateGUI() {
178                                    page.update();
179                                    if (success == 1) {
180                                            wiki.showWindow(
181                                                    new MessageWindow(
182                                                            "Conflict",
183                                                            "A sentence is in conflict with the current knowledge. For that reason, " +
184                                                                    "it cannot be added to the knowledge base.",
185                                                            "OK"
186                                                    )
187                                            );
188                                    } else if (success == 2) {
189                                            wiki.showWindow(
190                                                    new MessageWindow(
191                                                            "Error",
192                                                            "A sentence could not be added to the knowledge base because the knowledge " +
193                                                                    "base got too complex.",
194                                                            "OK"
195                                                    )
196                                            );
197                                    }
198                                    if (page != null) {
199                                            page.update();
200                                            page.getWiki().update();
201                                    }
202                            }
203                            
204                    };
205                    
206                    if (edit) {
207                            wiki.enqueueAsyncTask("Updating", "The knowledge base is being updated...", task);
208                    } else {
209                            wiki.enqueueAsyncTask("Updating", "The sentence is being added to the knowledge base...", task);
210                    }
211                    
212                    editorWindow.setVisible(false);
213            }
214    
215    }